Redux vs. Context vs. Prop Drilling
Note: This article was written in 2019 and now might be outdated.
One of the great things about React is that it allows you to build your app out of smaller components. You'll soon discover, however, that you need to share state between your components.
There are many options on how to do this:
- You can use Redux or other state management libraries like MobX
- You can use Context
- Or, you can just use plain old React props.
It’s nice to have options, but it also makes things a bit more complicated. Which one should you choose?
Plain old React props are for simple state that is nested 2,3 components down
Let’s start with the most simple solution - just passing React props down. This is also the most intuitive solution.
class App extends React.Component {
// initialize state in constructor omitted for space
render() {
return (
<div>
<h1>Hello this is app</h1>
<MyComponent data={this.state.data} />
</div>
)
}
}
You can share the state from a root component by passing it down as props. And you can also send callback functions to make child components update the state.
This method is straightforward - however, it often proves inadequate. When passing down props through only a few levels, it may suffice. But in larger applications, it can become challenging to keep track of the flow of data. In such cases, a more scalable solution may be necessary.
If you start on a new app and are uncertain about the requirements, it is advisable to begin with this method. As the application evolves and the needs become clearer, you can reassess and decide whether to refactor with Context or Redux.
It is worth noting that the latest version of React allows for the utilization of reducers, through the use of the useReducer hook, for managing state. While reducers were originally a concept exclusive to Redux, they can now be employed within React.
Context is better used for global switches such as locale or theme
With Context you don’t have to pass props around but the data is available inside the Context which is accessible from all child components.
const ThemeContext = React.createContext("light");
class App extends React.Component {
render() {
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
}
function Toolbar(props) {
return (
<div>
<ThemedButton />
</div>
);
}
In the example above you have the following component hierarchy: App
-> Toolbar
-> ThemedButton
. The data is sent from App
to ThemedButton
and the middle component Toolbar
doesn’t have to know anything about it.
Context is particularly useful when dealing with global data that is not overly complex, as demonstrated in the above example where the selected theme is a simple binary choice of dark or light. Other examples may include displaying the authenticated user at the top, the contents of a shopping cart or the selected language.
Since Context is part of React, you don’t need to install dependencies that make the app heavier. Another advantage with Context compared to Redux is that there is less boilerplate.
A state management tool like Redux is for complex application state
Redux is the most powerful solution. But it also takes a longer time to learn. Redux was originally developed many years ago to solve the problem with global data. This was before Context was publicly available.
What makes Redux special is the separation of reducers and actions.
Actions describe what happened, for example a user changed the theme. And the reducer describes how to change the state. In more complex apps the how to change the state can be quite complex. You might need to change many places in the state at once, and the state tree can be quite complex. This is the type of use case where Redux shines.
Redux also has powerful dev tools that give you a better developer experience. It’s integrated into your browser’s dev tools section.
The Redux dev tools is really useful, you can see what actions have been emitted and exactly how the state has changed after every action. It’s gold when working in more complex apps.
Other advantages with Redux are that you can use middlewares, the state management gets decouple from React, and there are some performance improvements
So to summarize, Redux is designed for handling more complex application state. The use of actions, reducers, middleware and dev tools all helps you work with complex app state. If your app uses more than a few state items, then Redux is probably a good idea.
The downside with redux is that it adds some boilerplate and a learning curve. But if you work with enterprise apps it’s worth the investment.