RecoilJS is meant to rock your React world

RecoilJS
is a state management library for React
which was made publicly available recently by Facebook
. The truth is that they have been using it for some time internally, so they finally decided to open-source it 😍
At the moment of this writing RecoilJS
is considered an experimental set of utilities and its API keeps on
improving rapidly. Personally speaking I have already tried to take advantage of its ways in a rather big
application of mine, with complex state management and many dynamic connections. I have to admit that I got amazed
with the efficiency, the simplicity and the flexibility it offers.
In my humble opinion RecoilJS
makes React
hell stronger. Let's see why.
# Why RecoilJS then?
No matter how much we love React
we have to admit that there are some tricky parts or even pain points when it
comes about state management with the Hooks API that is offered out of the box. To make it even more clear, we are
talking mostly about React.useContext
here and not about third party libraries like Redux
.
One of the issues we face when it comes about state management, is that the children components should constantly inform the ancestors. This might seem quite simple for small applications but for more complex ones, things start getting ugly especially when we are talking about long components trees which we force to get re-rendered with every change triggered by a nested child.
Another issue is that context can store mostly single values and not complex variations needed by different consumers.
All these force the 2 sides of the components tree to be tightly coupled. As declared in RecoilJS
docs:
Both of these make it difficult to code-split the top of the tree (where the state has to live) from the leaves of the tree (where the state is used).
So this is what RecoilJS is trying to accomplish. It tries to make our life easier by providing a Reactish API for even more flexible state management across complex applications.
In order to accomplish this, it defines a graph attached to our React components tree so that state changes flow from
atoms
which are the roots of this graph to our components through selectors
which are pure functions.
Here is a small representation that might help ypu visualize what is actually going on with atoms
:
# Show me an atom
Sure!! This is a dead-simple atom
named itemsState
:
As we said atoms
are units of state. Each atom
has a unique identifier, and a default value. For our examples we can
use a simple todo list.
RecoilJS
offers some hooks we can use to get access to atoms
state . We can use a hook named
useRecoilState
to access the list and apply changes to it or just the hook useRecoilValue
to pull the list only.
Let's see a real life example then:
Pretty straightforward right?
# Show me a selector
This is a dead-simple selector
named unfinishedItemsState
that pulls the unfinished items from itemsState
atom:
As we mentioned above, selectors are pure functions, and we use them to pull data from atoms
or even other selectors
. They can get both of these as input, and they get re-evaluated every time state changes. The components that
subscribe to them, re-render each time accordingly.
Let's create a more complex selector
by using unfinishedItemsState
selector:
We added a new one named unfinishedItemsCountState
that is pulling unfinished items from unfinishedItemsState
selector and
returns their length. Easy right?
Let's use unfinishedItemsCountState
in our component then:
Awesome!!
# Ok, what about native React hooks then?
Nothing special here. We keep on using React hooks same as we did before in our components alongside RecoilJS
hooks
.
As we saw above, useRecoilValue
hook returns the items list itself. How can we update this list then? We could use
useRecoilState
hook that exposes a method we can use to update the list accordingly.
Time to create a controlled input with the help of React.useState
and then take advantage of useRecoilState
hook to
add new items to our list:
So we created a controlled input by using React.useState
and every time the form gets submitted we are using
setItems
method - provided by useRecoilState
- to update the list in itemsState
atom.
The nice thing here is that the counter with the unfinished tasks gets updated automatically whenever we add a new todo item and this is done actually with the minimum effort. Pretty amazing, right?
# Ok, so how all these fit together?
RecoilJS
uses context to make these outstanding bindings, that is why we need to wrap our top-level App
component
with RecoilRoot
. This is a context provider provided by RecoilJS
and must be an ancestor of all components that
use atoms
and selectors
:
For sure we can have multiple roots and each of them has its own atoms with distinct values.
When we have nested roots the inner ones mask entirely the outer ones.
# Things we need to pay attention to
Obviously RecoilJS
makes React
state management way easier with the API it provides but there are more we haven't
touched yet and we should mention here:
- Selectors provide a very powerful API with a getter and a setter. we might find ourselves using a setter rarely but this actually gives even more flexibility to return writeable state from our selectors:
- Selectors can use Promises and pull data from an external resource in a dynamic fashion. Because of this we can run pretty complex logic with the minimum boilerplate:
- We can use
React.Suspense
to take care of asynchronous selectors:
- We can wrap our components or parts of the application with an
ErrorBoundary
since selectors can throw errors when something goes south:
RecoilJS
treats navigation and state persistence as first class concepts which is absolutely magnificent
So, that was it. I am sure you have lots of questions so I highly propose to play with it in an actual codebase and see how it goes. Feel free to use this codesandbox I put together with the examples above. Cheers!!
You can read the official documentation if you need to go deeper with RecoilJS
Did you like this one?
I hope you really did...
Newsletter
Get notified about latest posts and updates once a week!!
You liked it?