Recoil  - Ideal React State Management Library?
Tags: react, webdev, recoil, javascript
Published: 2020-06-07 20:48:36

In May 2020, Dave McCabe gave an interesting [talk](https://www.youtube.com/watch?v=_ISAA_Jt9kI&t=448s) about the new state management library called Recoil. The video clicked immediately with me and inspired to write this article. Recoil is the missing puzzle piece for state management in React.

## So why do we need another global state management library?
The reason we have so many different libraries of managing state in React, is that there is no oficial one yet.

Is Recoil an official one? No it is not.
{% twitter 1262143043928502272 %}

But what is particularly different from the rest, is that Recoil is specifically designed for React and feels like React.

## What's wrong with Redux? <a name="chapter-1"></a>

Redux is by far the most popular library for managing state out there, but it does not come without drawbacks. [Redux](https://redux.js.org/) same as [Recoil](https://recoiljs.org/) was designed for **performant**, **predictable** and **debuggable** updates of shared state. But let's take a look at what is not so great in Redux:

- **Ridiculous learning curve.**
Some of you might not agree with the learning curve, but to me, after I got more or less comfortable with React, I really struggled to understand Redux. Like, how to structure the project? how to store the state? where should my business logic go? Redux documentation is overwhelming, and I am sure it has all the answers to these questions, but to really nail them down, it would take you quite a bit of time.

- **Boilerplate – reducers, actions, connectors.**
Not many would disagree that Redux has too much boilerplate. If you are dealing with async data or caching computed selector values, you need to install third-party libraries solutions and add even more boilerplate. Additional code comes with the cost of having more bugs.

- **Restructuring of Business logic**
I think a Redux way of splitting business logic from the components, is not going very well with the React component based approach. Introducing Redux will require you to redesign the structure of your project.

- **No “concurrent mode” support YET.**
React [concurrent mode](https://reactjs.org/docs/concurrent-mode-intro.html) is very soon to be released. "Concurrent mode" is fixing fundamental limitation by making rendering interruptible. Not supporting "concurrent mode" will be a major drawback of the library. As of now, [React-Redux](https://react-redux.js.org/) does not support it, but it is planning to introduce `useMutableSource` hook, that will make it compatible with "Concurrent Mode".
{% twitter 1141127274487566336 %}

## What's wrong with Context API?
[Context API](https://reactjs.org/docs/context.html) is an utility coming from React core, specifically designed for solving the [prop drilling](https://kentcdodds.com/blog/prop-drilling) problem. As opposed to Redux, it is good to be used for low-frequency updates, such as theme or locale. But because of Redux drawbacks, Context API often becomes overused.
There are some drawbacks once we start using Context as a state management tool 

- **Unpredictable and not performant updates.**
Because of how it was designed, context lets you store only one single value per `Provider`. If you move your global store in the value of the Provider, you will be losing out on performance. When a React `<Context.Provider>` gets a new value, all the components that consume that value are updated and have to render, even if a component only cares about part of the state.

- **No way of creating context dynamically.**
Imagine if you have a list of items that you dynamically add or remove, and each item has to have its own context provider for isolation or for performance reasons.
![Dynamically inserting context](https://dev-to-uploads.s3.amazonaws.com/i/072xbe5j2407imjutcop.png)
Introducing another item would require placing another Context Provider at the top of the tree, which would cause the whole tree to unmount and mount again.

- **Context Hell**
Context API definitely has much less boilerplate then redux, but if you start adding them more and more, your react tree would look something like this.
![Context Hell](https://dev-to-uploads.s3.amazonaws.com/i/gniszxk43379pu7v5mom.png)

- **No code split support**
Because Context API introduces coupling between the roots of the tree and leaves of the tree, code splitting becomes nontrivial.


## So What is Recoil?
- **Very easy to learn, simple API.**
To get through basic API you would literally need 5 minutes. Here is a nice free [egghead tutorial by Tomasz Łakomy](https://egghead.io/playlists/up-and-running-with-recoil-a-new-state-management-library-for-react-78b8).
But also please check the [docs](https://recoiljs.org/docs/introduction/installation).

- **Minimal boilerplate and reactish approach.**
Recoil does have almost zero boilerplate, and it looks and feels very like just using simple `useState` from React. You only need to wrap your app once in `<RecoilRoot>`, and you can have as many independent global states as you like.

- **Performant granular updates.**
Recoil allows you to connect to the exact piece of state, which is a huge performance benefit. By creating an [atom](https://recoiljs.org/docs/api-reference/core/atom) you add a new global state, by creating a [selector](https://recoiljs.org/docs/api-reference/core/selector) you are adding a function that returns data derived from the given set of dependency values. Both `atom` and `selector` can be subscribable and writable.

- **Dynamically created state**
Recoil allows you to create dynamic global states, by using [atomFamily](https://recoiljs.org/docs/api-reference/utils/atomFamily) and [selectorFamily](https://recoiljs.org/docs/api-reference/utils/selectorFamily). Both atomFamily and selectorFamily accept an id, which will dynamically create a state or a selector function.
```javascript
const itemWithId = atomFamily({
  key: 'item',
  default: ...
});

 useRecoilState(itemWithId(id))
```
- **Async Support.**
Recoil comes with [async](https://recoiljs.org/docs/guides/asynchronous-data-queries#asynchronous-example) support without any third-party libraries. Derived data can be synchronous or asynchronous without modifying the components that use it.

```javascript
const fetchUserDetails = selector({
  key: "oooo",
  get: async () => {
    try {
      return await fetchUsers(url);
    } catch (error) {
      throw error;
    }
  }
});
```

- **No impact on code-splitting.**
Unlike Redux or ContextAPI, Recoil state is not stored globally anywhere, the state definition is incremental and distributed, which makes code-splitting achievable out of the box.

- **Concurrent mode support.**
As opposed to other state management libraries, Recoil is built on React primitives, it is using react state under the hood. For this reason, Recoil is not usable outside of React, but it works very well within React. As of the time of writing this article, Recoil does not have the "concurrent mode" support yet but is planning to achieve it with the use of `useMutableSource` hook in the near future.

## Conclusion
Of course, Recoil is not ideal and there are still many unknowns. But what I like most about it, is that using Recoil feels so much familiar than existing state management libraries out there.

Currently, the library is in a very early stage, but I am sure it has enough to get you excited. [Official Get Started](https://recoiljs.org/docs/basic-tutorial/intro)

Thanks for reading my thoughts on Recoil. This is my first article and I would be interested to hear your feedback.