React-Redux: understanding the data flow
One of the hardest things to understand for a beginner with Redux is the high-level flow of data from the component to the state and back. I found this to be frustratingly difficult to comprehend the first time I tried to jump into Redux, and there aren’t a lot of articles online that cover this topic specifically without going into unnecessary detail.
In this post, I’ll cover the basics of how Redux works with React from a high level perspective. I will also walk through what happens when a user inputs something that leads to a new state being created.
The Component is where everything starts in React-Redux. It is the thing that the user actually sees on their screen and interacts with. For example, a button or a list of buttons. This is mostly the same as your normal React component. In the component, you can create props, generate a chunk of html with your render function, or run any functions you’d like within the componentDidMount() function. However, there is one big difference about components that you should note when using redux: the component can NOT directly access state or change state. So how are you supposed to store information in your app? For that, we’ll need to make a container for the component.
The Container is a file that corresponds directly to a single component. Think of it like a literal container that you put your component in to ‘upgrade’ it. By using two container functions called ‘mapDispatchToProps’ and ‘mapStateToProps’, you can now link up your component’s props to state and action dispatchers (which are used to change state). If you had a div in your component that you want to display a property of state, you can simply make that div display a prop and then use mapStateToProps to link up that prop to state. If you want your component to store something in state, you can create a prop, call it as a function, and then use mapDispatchToProps to dispatch an action. That leads us to the next type of file your Redux program will need.
The Action Creator. In this file, you will write the functions that dispatch an action. These functions will be linked to your component props by the container’s mapDispatchToProps function. At that point, a component should be able to call a prop like a function and know that it will lead to an action getting dispatched. After the action is dispatched, it will be heard by only one type of function: the reducer.
The Reducer is the last step of the process. After ‘hearing’ an action get dispatched, the reducer can now generate a new state based on what the action wants it to do. Note the the state never actually changes in Redux, but instead the reducer generates a new state which is a copy of the old state, but with some sort of modification.
Now, I’ll walk through a simple example to show how a user input could trigger a state change that is reflected by a different part of the screen.
- The user clicks a button in the app and a component prop is called like a function.
- The corresponding container dispatches an action. This happens because the prop (which was just called in the container) is tied to an action dispatcher using mapDispatchToProps (in the container).
- A reducer ‘hears’ that action and runs a function which returns a new state with specific modifications.
- The container ‘knows’ that state has changed and modifies a specific prop in the component as a result of the mapStateToProps function.
- The component now has a prop that has officially changed due to a new state being generated, so if that prop is responsible for any any visible UI, the user will see it change automatically.
In my next post, I’ll go into more detail about what the file structure for a React-Redux app should look like and I’ll also give some examples of what these files look like.