Dispatching actions
in Redux is the fundamental method of updating a Redux store's state
. Actions are used to store relevant information for the state
, and they reach the store through the dispatch()
method available on the store
object. You can use either store.dispatch()
directly or this.props.dispatch()
for dispatching these actions. This guide walks you through the comparison between the two methods to help you understand which method is better and why.
Actions hold or store information that needs to be passed to the Redux store
, and this information is grabbed from the component where the action
is dispatched. This means that while your store may hold information pertaining to a number of components, it can be considered an independent module in your system. Your components need not know what state
they're updating—their prime concern should be dispatching the necessary action
. The remaining computation is handled by the reducer
and the store
itself.
For instance, if you have a Profile
component that displays the details of your profile and a Navbar
component that opens a popup where you can edit your profile information, the component definition isn't sufficient to figure out that the Navbar
component would interact with your store containing the profile details. Your store
sits at the top level of your app's hierarchy with the components sitting at the lower level, making it redundant to import it as a lower-level module inside each component.
Consider the following code where you have a store
and and a reducer
that dispatches a default action of type ADD_USER
. Here, the store
directly uses the store.dispatch()
method to dispatch an action.
1import { createStore } from 'redux'
2const store = createStore(users, null)
3
4const addUser=(user)=> {
5 return {
6 type: 'ADD_USER',
7 user: user
8 }
9}
10
11store.dispatch(addUser(user))
Now consider a use case where a component in your app needs to dispatch the same action. In this case, your component is unaware of the store it's interacting with, but its direct parent component connects to the store and dispatches an action for the child component using this.props.dispatch()
.
1@connect(store => ({ myStore: store.myStore }))
2class UsersContainer extends Component {
3 AddUser = (newUser) => {
4 this.props.dispatch(type:'ADD_USER', newUser);
5 }
6
7 render() {
8 return (
9 <UsersComponent
10 onAddUser={this.AddUser}
11 />
12 }
13}
UsersComponent
simply fires a function, and its parent component, UsersContainer
, dispatches the ADD_USER
action using this.props.dispatch()
. UsersContainer
connects with the store
, hence it knows which store it's interacting with. In a practical app, you would have a component tree where deeply nested components would need to interact with a high-level store. Every time you dispatch an action, it's possible that you might want to interact with a different store.
1@connect(store => ({ myStore: store.myStore }))
Thus, using the connect()
function as shown, dispatch()
is passed as a prop
to its child components from where the necessary action is dispatched.
It is evident now that this.props.dispatch()
is a more logical and better approach to dispatching actions in Redux than using store.dispatch()
directly, as it makes sure that your Redux store does not become a singleton module. Most of the time, dispatch()
is called from within the store consuming components and, similar to this.props.dispatch()
, you can also dispatch actions by mapping it with props using the mapDispatchToProps()
method and passing it to the connect()
function for a cleaner syntax. Alternatively, you can explore libraries like Redux Saga and learn more about dispatching Async actions in its official documentation.