Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Asynchronous ActionCreator in React Redux

I'm pretty new in React-Redux. Was working on an application. The thing is that I faced some issues with asynchronous execution of Redux actionCreator, may be.

Below is my component. Say, I want to call an actionCreator from componentDidMount() or from an onclick event listener.

class Dashboard extends PureComponent {

     componentDidMount() {

          this.props.getProductsAndPackages();

          let something = [];
          something = this.props.products;

     }
....................................
}

Or , the function this.props.getProductsAndPackages(); can be an onClick event handler that does the same thing, context is the same. I'll ask my question after first explaining my code.

At the lower side of my Dashboard container:

Dashboard.propTypes = {
getProductsAndPackages: PropTypes.func.isRequired,
products: PropTypes.array.isRequired,
.......................

 };

const mapStateToProps = (state) => {
    return {
         .....................
         products: state.products.products,
         ...................
    };  
};


const mapDispatchToProps = (dispatch) => {
    return {
        getProductsAndPackages: () => dispatch(getProductsAndPackagesActionCreator()),
    };
};

export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Dashboard));

My actionCreator goes like:

export const getProductsAndPackagesActionCreator = () => {

return (dispatch) => {

    dispatch(productsIsLoading(true));

    let url = 'xyz';

    if(!!localStorage.getItem('_token')) {
        const local_token = localStorage.getItem('_token');
        const fullToken = 'Bearer '.concat(local_token);

        axios.get(url, {headers: {Authorization: fullToken}})
            .then(response => {
                dispatch(productsIsLoading(false));
                if (response.data.statusCode === 200) {
                    dispatch(productsFetched(true));
                    dispatch(products(response.data.data));
                } else {
                    dispatch(productsFetched(false));
                    dispatch(productsErrors(response.data.message));
                }

            })
            .catch(error => {


            });

    } else {

        axios.get(url)
            .then(response => {
                dispatch(productsIsLoading(false));
                if (response.data.statusCode === 200) {
                    dispatch(productsFetched(true));
                    dispatch(products(response.data.data));
                } else {
                    dispatch(productsFetched(false));
                    dispatch(productsErrors(response.data.message));
                }

            })
            .catch(error => {
                console.log(error);
                dispatch(productsIsLoading(false));
                dispatch(productsErrors(error.message));

            });

    }


};
};

Now, I want my getProductsAndPackagesActionCreator() to return a Promise or anything that would allow my something variable to get the actual data returned from the server. Right now, by the time I'm getting actual data, the line something=this.props.products has already been executed and I get back the initialValue that was set for products.

I know, whenever I'll receive the populated products, component will re-render, but that does not help my decision making.

I'm using redux-thunk, by the way.

What should I do now ? Sorry for such a long post.

like image 522
Plabon Dutta Avatar asked Aug 07 '18 09:08

Plabon Dutta


People also ask

Are Redux actions asynchronous?

By default, Redux's actions are dispatched synchronously, which is a problem for any non-trivial app that needs to communicate with an external API or perform side effects. Redux also allows for middleware that sits between an action being dispatched and the action reaching the reducers.

What is action creator in Redux?

An action creator is a function that literally creates an action object. In Redux, action creators simply return an action object and pass the argument value if necessary.

Is redux-thunk asynchronous?

Thunk functions can be used for both asynchronous and synchronous logic.


1 Answers

Actually I wanted getProductsAndPackagesActionCreator() to return a promise, which was pretty straightforward, to be honest. I figured out that if you just return the axios.get() or axios.post(), it will return a promise. So, the modified code looked like below:

export const getProductsAndPackagesActionCreator = () => {

  return (dispatch) => {

    dispatch(productsIsLoading(true));

    let url = 'xyz';

    if(!!localStorage.getItem('_token')) {

        return axios.get(url, {headers: {Authorization: fullToken}})
            .then(response => {
               ............
               ............
            })
            .catch(error => {


            });

    } else {

        return axios.get(url)
            .then(response => {
                ...........
                ...........
            })
            .catch(error => {
                console.log(error);
            });
    }
  };
};

And then, I could do something like below in componentDidMount() or on any onClick event:

this.props.getProductsAndPackages().then(() => {
    this.setState({
        ...this.state,
        clicked_product: this.props.product_by_id
    }, () => {

       //do other stuffs

    });
});

Feel free to let me know if there's any issue.

like image 175
Plabon Dutta Avatar answered Oct 13 '22 18:10

Plabon Dutta