Wherever you see React, it tends to be paired with something called Redux. But what exactly is this Redux thing all about? In this two-part post, I'm going to go through the details, but to quickly summarize:
Redux provides a Store object, accessible from anywhere in your React app, which contains the state of the entire application, as well as the data flow pattern for how to interact with it.
Here's a diagram outlining this pattern. Don't worry about understanding it yet, I'll be talking through each of the different parts a little bit later.
A common pattern in React is to have a container component which contains logic to create and render multiple child components.
These child components are where the data is actually displayed. Since the container is where they get created, the container will need to hold all the data, it does this in an object called state. Data can be retrieved from state using a getState() function, and the info in state can be changed using setState(). In order for this data to get displayed; however, we need to get the data from the container and into the child. We do this by passing down "props" (short for properties). Here's a very simple example of what this flow looks like, as well as a visual example of how it might render:
To provide a real example, think of a Digital Photo Board. We might have the container (the green square) styled to look like a cork-board, while the photos themselves (blue squares) would be contained within it:
Easy enough, but what if we wanted that child component to be able to change the state object? For example, if the child was a grocery list and had an 'add to list' button that lets a user type into a field, press that button, and then that input would be added at the end of the list. How would that work in React?
Well we'd set up the state in the container component with an entry like
list: [item1, item2, item3], then render a child component and pass down the prop
<childComponent list=state.list>. This is just like our earlier Photo Board example, but there's a problem here. In this child component, we have our 'add to list' button, but it can't just throw another line onto itself, it needs to actually update the state. Otherwise whenever there's a re-render the new entry will disappear. But if you look at the data flow diagram you'll notice a really important aspect - it only goes one way. So, what do we do?
The solution is to define a function in the container that will update its state, then pass that function down as a prop. This way, the event on the child component will call the function, which is within the container component's scope (so it has access to state), and can pass in whatever data it would like as an argument, such as our new list item for example. Now we've established a two-way dataflow.
A fair question and the fact is, when it's this simple, there's no need for Redux. But in the real world things aren't always this simple.
For example, imagine that we now have multiple types of related components on a page, within separate containers, and when we make a change to one component we want all of its related components to change too. Perhaps this is a roster program that tracks some scores for each player. We don't want to hunt down the individual on the actual roster tree every time someone scores, so we have a list of player cards at the bottom where we can change their data which will then push up to the roster tree.
Think about what we'd need to do to set that up. Where would we define our state so that it's accessible to both container components? How is the data passed around?
The only way to accomplish this would be to create another container component which is a parent to both of our existing containers. We would set up the state, and the function to change that state here. This would then pass props down to both containers, and these containers would in turn pass their props down again to their child components to be displayed. Of course, that means that to change the state, we'd need to pass the function prop UP through multiple layers as well. Then, once the state has been changed it'll need to go through the whole props chain again to render the changes made.
Wow, that just became a lot of steps really quickly! And this still isn't a terribly complex scenario. Imagine if we had many different containers with related components across various layers, this would quickly get very confusing, and very taxing. This is where Redux comes in handy.
In Part 2 I explain what Redux does to simplify this situation for us, how to actually use Redux (aka what are the parts in the first diagram), and walk through the same roster example using Redux.