Editor's Note: We are excited to have a guest blogger on our blog for this post! Mark Erikson (@acemarke) is a software developer and one of the maintainers of the Redux library. He is writing a tutorial series called “Practical Redux”, which covers some tips, techniques, and concepts useful to developers who want to use Redux in “real-world” applications.
props down to child components or using callback functions to send data back up to a parent.
At first glance, it might seem somewhat confusing to use Redux in a React application.
Don’t components have their own state?
Why would you need to add more state to your application, or use another tool to help manage that state?
React is great, and it’s entirely possible to write a complete application using nothing but React. However, as an application gets more complex, sometimes it’s not as straightforward to use plain old React. Using a state management library like Redux can alleviate some of the issues that crop up in more complex applications.
If you read about Redux, you’ll see several benefits that are commonly discussed:
- Predictable state updates make it easier to understand how the data flow works in the application
- The use of "pure" reducer functions makes logic easier to test, and enables useful features like "time-travel debugging".
- Centralizing the state makes it easier to implement things like logging changes to the data, or persisting data between page refreshes
In addition to those general benefits, Redux provides some advantages to maintaining state in a React application. Here’s a couple examples.
Some components may need to access the same state but display it in different ways. A good example would be a classic "master / detail" view, where you have a list of items that shows a few summary values from each item (the master), and also a display component that shows all the details for the currently selected item (the detail).
The problem we run into with master/detail views is the question of where our data should 'live'. Having two components that share the same data can make it messy when we want to keep our data "in sync". Ideally the source-of-truth of the data is only in one place.
When we have two children who need access to the same data, the React docs encourage you to "lift state up", which means putting the data in the nearest ancestor of the two components.
In this simplified example the two components are direct siblings. However, if these two components are very far apart in the tree, the "nearest ancestor" component might be at the top level of the component tree. This would mean that the ancestor would have to pass the data down as props, through several other intermediate components along the way.
props in this manner can become confusing to trace. It also makes it harder to move components around because there is a coupling between
- the component and its parent (for props this component itself may not care about) and
- the component's children that it's passing props to (that again, the intermediate component may have no use for these props it's simply passing along).
It also could be a performance issue, since every update to the data would cause all the children to re-render.
Redux helps us in these tricky scenarios where multiple components want to share some or all of the same data, but are not closely related to one another. Redux provides a central store that can hold data from anywhere in the application. In Redux, a
In the master/detail example, the list can extract the names of all items in the list and render them, and the detail component can extract and show all the attributes of the one item.
This means the data no longer has to be passed down through multiple levels of components. This can make the code simpler, and since fewer components are involved, it can also improve rendering performance.
Redux, just like React, follows a strict, one-way data flow. This is beneficial for many reasons, as outlined in the Redux documentation:
All data in an application follows the same lifecycle pattern, making the logic of your app more predictable and easier to understand. It also encourages data normalization, so that you don't end up with multiple, independent copies of the same data that are unaware of one another.
When updates to the
store are necessary, the path for updating the data in the
store follows the same flow every time, no matter where the update is coming from, whether it's from a user inputting data into a form or fetching data from a REST API. Just as all rivers lead to the ocean, the data in a Redux application flows in one direction to lead to the
Redux also helps us save time when developing because we can "hot-reload" and retain our app's state. Hot reloading is ability to automatically reload parts of your code whenever you save a file, without having to refresh the entire page. A build tool like Webpack can be configured to watch your source files on disk, and the application code can listen for “file reloaded”-type events. When a reload event is received, the application can replace the old version of the code with the newly updated version, such as the latest version of a React component file.
Unfortunately, hot reloading React components will wipe out your existing component tree, including any state stored inside of them. That means that if you had spent time interacting with your application in development, and only had that data in React component state, the hot reload would effectively throw away all that data and reset your UI back to its original state. Keeping the state separate from the UI tree allows the UI tree to be swapped out and reloaded with the updated components, while keeping your current development state the same.
However, when Redux-connected components are reloaded, they will immediately read the current data from the Redux store, and render that data with the updated code. This gives you the ability to effectively "live-edit" your UI, and makes the development process much faster.
Overall, it's certainly true that you can write an entire application using nothing but React's component state. Redux’s creator Dan Abramov says that people often jump into Redux too early, and wrote an article called "You Might Not Need Redux" to encourage people to think about why they want to use Redux. That said, there are some great reasons to use Redux in a React application (or even with other frameworks, like Angular). As with any technology, there are tradeoffs involved, but from my perspective, using Redux is absolutely worth it.
The original inspiration for this post came from Mark's answer to a Stack Overflow question regarding Redux and its benefits
If you'd like to learn more about Redux, check out Mark's series "Practical Redux", his React/Redux Links Github repository which contains a comprehensive collection of articles and tutorials on React & Redux and of course purchase our book!
To keep up to date with the latest news, libraries and features of React and Redux, subscribe to our weekly newsletter