blog.jakoblind.no

When to use Redux, Context and props

One of the things that make React so awesome is that you build your app out of smaller components. But quite quickly you realize you need to share state between your components.

Today you have many options on how to do this:

  • You can use Redux or other state management libraries like MobX
  • You can use Context
  • And 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 thing - just passing React props down. You know, like the way you do when you first learned React. This is the most simple and 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>
    );
  }
}

const MyComponent = props => (
   <div>{props.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 simple - and many times is way too simple. When you just need to pass down props 2,3 levels down its fine. But if your app is bigger than that, you will quickly find yourself in a callback hell and you’ll lose track of what’s going on. Then you need a more scalable solution like Context or Redux.

If you start on a new app and you don’t know what you need - start with this. Then you learn as your app grows what type of solution you need and you can refactor to use either Context or Redux.

It’s good to know that with the latest version of React you can use reducers for setting state with the useReducer hook. Reducers is originally a Redux concept but you can use them as part of React.

Context is for global switches such as selected language or color 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>
  );
}

class ThemedButton extends React.Component {
  static contextType = ThemeContext;
  render() {
    return <Button theme={this.context} />;
  }
}
Copied from the official docs

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 very useful when you have global data that is not very complex. Like in the example above where it’s the selected theme which can be either dark or light. It’s a trivial setter/getter type of state. Other examples could be showing the authenticated user at the top, the content of the cart or the selected language.

Context is part of React. The advantage with this is that you don’t need more 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 longer time to learn it. Redux was originally developed many (4 maybe?) 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.

redux set state 1

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.


tags: