Previously in my “React-Redux for Newbies” series I discussed the value of using Redux in a React app and provided a high level overview of reducers. In this article I will cover Redux actions and the role they play in a React-Redux environment. If you need a refresher about why applications use Redux or the intent of reducers, please review the earlier posts from this series.
Before jumping into what actions are, let’s set the landscape of where actions live in React-Redux.
As displayed in the diagram above, actions sit between our React view and our Redux reducer. Thinking about the general definition of an action and combining that with our understanding of reducers, this diagram seems logical. In order for an action to take place, a user must trigger an event on the UI. We know that reducers take the current state and an action as arguments to update the store. Finally our React components re-render based upon the updated version of our store.
What are Redux actions?
{type: ‘ADD_RECIPE’}
If we are creating a recipe book application and this action was triggered we would expect a new recipe to be added to our store. As is, our action would not be able to do that. We are missing the recipe information. A more functional version of our add recipe action would like this:
{type: ‘ADD_RECIPE’, recipe: recipe}
Where we include the recipe we are adding. Now in our reducer if our recipe book is an array of recipe objects we can just concat the recipe book with the new recipe.
Redux Connect
Connect has four optional arguments mapStateToProps, mapDispatchToProps, mergeProps, and options.
mapStateToProps passes state as the first argument to our mapStateToProps function. Enabling us to connect our component properties to our state, which will update our component whenever there are changes to the state. We can pass null or undefined as the first argument to prevent our component from being notified of store updates. However, if we intend to subscribe to updates we must ensure our mapStateToProps functions returns an object like shown below.
const mapStateToProps = (state) => { return { recipes: state.recipes } }
The second argument mapDispatchToProps passes dispatch as the first argument to our mapDispatchToProps function. This function is what we will use to dispatch our functions and notify the store of changes. This parameter does not have to be a function, it can be an object or undefined depending on your needs. Like mapStateToProps, mapDispatchToProps must return an object. The object properties should contain functions that dispatch actions. For this example, we will make it a function:
const mapDispatchToProps = (dispatch) => { return { addRecipe: (recipe) => dispatch({type: ‘ADD_RECIPE’, recipe: recipe}) } }
The other two parameters we will ignore in this article. Before discussing about dispatching action, I would like to point out that the connect function returns a Higher Order Component which we use to wrap the component we intend to connect to the store.
Dispatching Redux Actions
In Redux we can dispatch actions in two ways, within our component directly or using mapDispatchToProps. If we pass null or undefined to mapDispatchToProps within connect, dispatch will be passed to our component as a property by default. We dispatch actions within our component like:
onClick={() => props.dispatch({type: ‘ADD_RECIPE’, recipe: recipe})}
Using mapDispatchToProps like we defined earlier, our component no longer needs reference to dispatch. Therefore we will dispatch actions like so:
onClick={props.addRecipe}
Redux Action Recap
Redux actions are JavaScript objects with a ‘type’ property that informs us that a specific event has occurred within our application. When dispatched, we can update our application’s store and perform other business logic based upon the action type or any other information that is included within our action. In order to connect our actions and reducer to our store, we must use the Redux connect function.
Have more questions about React-Redux? Contact us or checkout our other posts about React-Redux.