lavender
lavender

Reputation: 67

Call to multiple dispatch for async action generators

//Action Generator
   export const userActionGenerator = () => {
        return function (dispatch) {
             axios.get(`https://jsonplaceholder.typicode.com/users`)
             .then((resp)=> {
                  //First Call to Dispatch 
                  dispatch({ type: 'GETUSER', payload: resp.data});
             })

        }       
            
   }


//Component
  import React, { Component } from 'react';
  import { connect } from 'react-redux';
  import { userActionGenerator} from '../store/appStore'

  class Users extends Component {
      render() {
           console.log(this.props)
           return (
              <div>
                Users Component
                <button onClick={this.props.getAllUsers}>
                Load Users</button>
                {this.props.data.map(item => {
                    return (
                        <div key={item.id}>
                            <h1>{item.name}</h1>
                        </div>
                    )
                })}
              </div>
           )
       }
   }
   const mapStateToProps = (state, props) => ({data: state.users})
   const mapDispatchToProps = dispatch => (
            {
                getAllUsers: () => {
                    //Second Call to Dispatch
                    dispatch(userActionGenerator());
                }
            }
        )
   export default connect(mapStateToProps,mapDispatchToProps)(Users);

Calling "userActionGenerator" directly without "dispatch" is not giving any response, i could make it work by calling dispatch passing "userActionGenerator" function call. But i fail to understand why do we need to call dispatch in the component again when the action generator has already invoked it.

Upvotes: 2

Views: 450

Answers (2)

Naveen Vignesh
Naveen Vignesh

Reputation: 1359

Using bindActionCreators is what you might need. Here is official docs. Please go through it.

import { bindActionCreators } from 'redux';

// Using bindActionCreators you don't need to use dispatch
const mapDispatchToProps = dispatch => bindActionCreators({
  // actions
  userActionGenerator,
  // action1,
  // action2,
  // ...
}, dispatch);

And in your actions file you have to write is as such.

const userActionGenerator = (...args) => dispatch => {
  dispatch(object1);
  dispatch(object2);
};

Upvotes: 0

Sagiv b.g
Sagiv b.g

Reputation: 31014

Your action creator is actually a thunk.
When you dispatch it, the redux-thunk middleware will catch it and will invoke it.
Normal actions should be objects not functions, but redux-thunk allows you to dispatch functions:

if (typeof action === 'function') {
  return action(dispatch, getState, extraArgument);
}

When that function is invoked by redux-thunk it will have to dispatch a real action (an object), that's your second dispatch.

So this is the flow:

dispatch(userActionGenerator());

redux-thunk will catch this because userActionGenerator returns a function and not an object, it will invoke the returned function, while passing it (dispatch, getState, extraArgument):

return function (dispatch) {
   axios.get(`https://jsonplaceholder.typicode.com/users`)
   .then((resp)=> {
       //First Call to Dispatch 
       dispatch({ type: 'GETUSER', payload: resp.data});
     })
} 

This returned function is dispatching an object, meaning redux-thunk will ignore it and will let the reducers (or other middlewares down the chain) handle this action.

Upvotes: 1

Related Questions