loading...
Cover image for Redux vs Recoil: which should you use?

Redux vs Recoil: which should you use?

emma profile image Emma Goto πŸ™ Originally published at emgoto.com on ・4 min read

Recoil, Facebook's experimental state management library for React, has been receiving a lot of hype. With Redux being the most popular state management library, it's natural to ask the question - when does it make sense to use one over the other?

Let's take a look at some API differences between the two, plus some potential performance wins for Recoil.

Redux Stores vs Recoil Atoms

In Redux, we have the concept of a centralised store where all the data for our app lives.

In a simple to-do list example, your store would look something like this:

{
    listName: 'My cool to-do list',
    tasks: {
        '1': {
            name: 'My first task',
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Recoil instead splits your state into individual atoms. You would have one atom for listName, and another for tasks. Here’s how you would create the atom for your tasks (from the Recoil docs):

const todoListState = atom({
    key: 'todoListState',
    default: [],
});
Enter fullscreen mode Exit fullscreen mode

At ReactEurope, the creator of Recoil, Dave McCabe, also introduced the possibility of creating individual atoms for each of your items:

export const itemWithId =
    memoize(id => atom({
        key: `item${id}`,
        default: {...},
    }));
Enter fullscreen mode Exit fullscreen mode

This means we could break it down further, and create an individual atom for each task.

Redux vs Recoil: Performance

McCabe mentioned in a comment on HackerNews:

"Well, I know that on one tool we saw a 20x or so speedup compared to using Redux. This is because Redux is O(n) in that it has to ask each connected component whether it needs to re-render, whereas we can be O(1)."

Recoil is O(1) because when you edit the data in an atom, only components subscribed to that atom will re-render.

In our to-do list example, if we had 20 separate tasks, we would have 20 separate atoms. If we edited the fifth task, only the fifth task would need to re-render.

Redux does allow you to achieve the same effect using selectors:

// selector
const taskSelector = (id) => state.tasks[id];

// component code
const task = useSelector(taskSelector(id));
Enter fullscreen mode Exit fullscreen mode

With Redux, the component will only need to re-render when the specific task re-renders - same as Recoil.

The caveat here is that each time any part of the state changes, our taskSelector would have to re-calculate.

We can use optimisations like createSelector to reduce expensive calculations. However it will still need to check whether it needs to re-calculate.

With these performance optimisations, Recoil makes sense for huge apps that need to render a lot of components. A regular app is probably going to perform just fine with Redux. Idon’t think it’s worth switching to Recoil for the potential (maybe nonexistent) performance benefits.

Redux vs Recoil vs Context

You might also be wondering - what about React Context? Do you need a state management library at all?

Using React Context does have some potential downsides when it comes to performance. Any changes to state will cause re-renders for components that are using that state.

I have a separate post on React Context that explains this issue, and provides a workaround library you can use called React Tracked.

Redux vs Recoil: API

So performance might not be the reason you need to switch to Recoil, but we can also compare the API of both libraries.

I'll be comparing Redux Toolkit with Recoil, to create a simple example that lets you change the value stored in a text box.

πŸ’‘ What is Redux Toolkit?

Redux Toolkit is a helper library aimed to help you simplify how you use Redux. If you're interested in learning more, I have a separate post on Getting started with Redux Toolkit.

Redux state management example

Recoil state management example

I also have to-do list examples of both Redux Toolkit and Recoil and other libraries over at react-state-comparison.

Redux vs Recoil: API differences

Comparing the differences in API between Redux and Recoil:

  • Both libraries need you to wrap the entire app in a provider component
  • Recoil lets you initialise a store using atom(). This also comes with a selector and dispatchable action built-in
  • Redux lets you create a store using createSlice() together with configureStore(). This comes with actions and a reducer. You'll need to define a selector separately
  • Redux also requires the useDispatch and useSelector hooks to be able to dispatch actions and use selectors

Redux definitely does have some additional boilerplate to get started!

Conclusion

To summarise some of the differences between Redux and Recoil:

  • Even with Redux Toolkit, Redux is still more "boilerplatey" than Recoil
  • Recoil may provide performance benefits, but only if your app is complex enough
  • Recoil is still in an experimental phase, while Redux is an established library

Another thing to point out is that Redux provides middleware functionality, while Recoil does not yet support it.

Recoil does have some nice-looking benefits - it is possibly more performant, and has slightly less boilerplate to get started. However, it is still worth keeping in mind that it is an experimental library. So there are some risks you will be taking on if you choose to use it for a large project.

Discussion

pic
Editor guide
Collapse
merri profile image
Vesa Piittinen

Redux centralization is bad when you consider the amount of initial JS you need to load. It is hard to code split the centralized Redux store (if you have a large existing one). This means oftentimes all the code related to state changes are served on the initial JavaScript bundle. This can become an issue as once your JS grows too big it will start having an effect to people and their first impression of your site's performance is poor and may leave due to that.

Recoil does not suffer from this.

The good part about Redux store is the ease for providing initial state for hydration. Haven't used Recoil so I don't know if it is possible to do a SSR and share the resulting initial state to client.

Collapse
emma profile image
Emma Goto πŸ™ Author

That's an interesting point I hadn't thought about - it looks like there are ways to code split your Redux store but Recoil certainly does make it easier since you don't have to do any extra work to set it up.

Collapse
rubiin profile image
Rubin

Recoil is not mature enough to replace redux. Tbh, you can use recoil on some of your personal small projects just to get to know it better but replacing an existing implementation of redux on stable company project will bring you a whole lot of pain

Collapse
emma profile image
Emma Goto πŸ™ Author

For sure, replacing Redux completely might not make sense. I could see some projects replacing a portion of their Redux state management with Recoil, if their app is complex enough that Recoil provides some performance benefits. But yeah, that will probably come only once Recoil gets closer to v1.0 and is a bit less risky to pick up.

Collapse
miketalbot profile image
Mike Talbot

I've never really like Redux due to the whole centralised principle and significant redrawing, but I built and use the lib below in my projects, this is also O(1), but uses named mappings into global or document state. I'm keen to try out Recoil to see if it has any advantages.

Collapse
emma profile image
Emma Goto πŸ™ Author

Thanks for the comment, Mike! That library looks pretty impressive.