React-Redux: understanding components, containers, actions, and reducers
Last week I wrote a post about a high-level overview of react-redux and how the pieces work together. Now, I’ll write more in depth about what each one of these functions look like and how it works.
- The component
This is the simplest one. For the most part, components in react-redux are similar to those in vanilla react. Check out the example code below:
This is a pretty normal and typical react component, with a componentDidMount function and a render function. Note that it makes no reference to state in this file; that is not handled by the component in redux.
Now let’s say I wanted to make my buttonListState prop actually reflect what is in state. Let’s take a look at how to do that.
2. The container
The container is the function (usually in a separate file) which gives the component props the special ability to interact with state. This is achieved using 3 functions. The first, mapStateToProps, used to link a property of the state object with a prop in the component. The second, mapDispatchToProps, is used to link a component prop to an action (which, when dispatched, leads to a new state being generated). Lastly, the connect function specifies which component the container should be hooked up to. Example code below.
In the example, I use mapStateToProps to ‘link up’ the buttonListState prop in my component to state.addButtonClick. Now when that state property changes, so will my component prop. I also use mapDispatchToProps to link up my updateStateFromServer component prop to dispatch the updateStateFromServer action. Now whenever that prop is called in my component, I know that action will be dispatched.
3. The action dispatcher
This one is pretty straightforward. All it does is return an action that the reducer will ‘hear’. It is typical for all the actions in an app to be in one file together with nothing else inside. I provided two example action dispatchers below:
The toggleSettings action dispatcher, which is linked to another component prop in another file using mapDispatchToProps, is the simplest possible example. All it does is export an action of type ‘SETTINGS_TOGGLE’ which a reducer somewhere is listening for. UpdateStateFromServer is a little more complicated because it makes an AJAX request before dispatching any actions. It is typical for any HTTP requests within the action dispatcher in a react-redux app.
4. The reducer
So, after those actions get dispatched, where do they get handled? That happens in the reducer. In most react-redux apps, there will be a separate folder that holds all reducer functions.
Also note that for each reducer, there will be one extra property of state. So, if your app has a users reducer, a messages reducer, and a notifications reducer, your state object will have 3 properties. Each reducer function modifies only that property of state.
Above is the simplest possible example of a reducer. When the action ‘SETTINGS_TOGGLE’ is dispatched, the action will cause state.toggle to be the opposite of whatever it was before. Note that on line 1, I set state = false. This means that state.toggle will be set to false by default when my app is loaded. It is important that the reducer has a default case, and that the state is set to something by default.