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',
}
}
}
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: [],
});
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: {...},
}));
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));
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. I donβ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 withconfigureStore()
. This comes with actions and a reducer. You'll need to define a selector separately - Redux also requires the
useDispatch
anduseSelector
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.
Top comments (6)
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.
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.
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
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.
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.
An angle on React state you haven't seen before...
Mike Talbot γ» Jun 29 γ» 10 min read
Thanks for the comment, Mike! That library looks pretty impressive.