DEV Community

Robert Marshall
Robert Marshall

Posted on • Originally published at robertmarshall.dev on

An Intro to React Recoil - The New State Management Library

What is Recoil?

Recoil is a minimal experimental state management library for React by Facebook.

If you have used Redux or React Context with Providers, the concept is very similar. You set a RecoilRoot (or Provider) somewhere in the parent tree. This will then provide context to all of the child components within.

Why Recoil instead of Context or Redux?

Existing state management systems like Context work well for their particular use cases. Redux for example can be very helpful when scaling a large application. However both Redux and Context have certain limits such as flexibility and performance. Due to the way that some libraries require code to be written, when scaling – this code can become bug prone.

Recoil provides the following benefits:

Flexible Shared State

Components across the React tree are able to be completely synced with less of a performance hit on the browser.

Derived Data and Queries

A simple and efficient way to implement calculations on changed state. Each packaged into its own block to allow faster development, better DX and less bugs.

App-Wide State Observation

Much like Redux – Recoil supports time travel debugging, undo support and logging.This way of being able to fully observe the state and what is happening was not possible with Context, and is fairly plug and play.

How To Use Recoil

There are a few essential pieces that Recoil needs to function. These are:

  • RecoilRoot
  • Atom
  • Selector
  • useRecoilState
  • useRecoilValue

There are other hooks that can be used, but these will get you moving.

What is RecoilRoot?

RecoilRoot can be thought of as the ‘provider’ of the app context or state.

A simple example of using the RecoilRoot looks like this:

import { RecoilRoot } from "recoil";

function AppRoot() {
  return ( 
  <recoilroot> 
   <componentthatusesrecoil /> 
  </recoilroot>
); }
Enter fullscreen mode Exit fullscreen mode

Multiple Recoil roots can be used together within an app, with the newest – or innermost root taking completely masking any of the outer roots.

The state that has been passed down from the Recoil Roots can then be accessed by Atoms.

What is an Atom?

If you have used the useState hook before, Atoms are very similar. Atoms are used with useRecoilState to get or set a single piece of state from its Recoil Root context. The Atom is the name and the value of the state – like a key within a database. They are a changeable, subscribable piece of state.

When an Atom is updated, any components that are subscribed to that state are re-rendered with the new value.

Each Atom must be completely unique, so requires its own unique ID known as a key.

An example of how an Atom is used:

import {
    atom, useRecoilState
}
from 'recoil';
const counter = atom({
    key: 'myCounter',
    default: 0,
});

function Counter() {
    const [count, setCount] = useRecoilState(counter);
    const increment = () => setCount(count + 1);
    return ( 
       < div > Count: {count} 
   <button onclick="{increment}">Increment</button> 
</div > 
); }
Enter fullscreen mode Exit fullscreen mode

The great part about Atoms is that they can be declared in a module outside of a component, much like React Hooks, and then imported into a component when needed. This makes sharing state far easier than before.

What is a Selector?

Selectors are pure functions that take Atoms as an input. Much like Atoms they need a unique key to identify them. A Selector is used to compute calculations that rely on the state.

When an Atom state updates, the selector listens to this – reruns its calculation – and returns the changed value. Components are able to subscribe to Selectors in the same way they can subscribe to Atoms.

An example of how to use Selectors:

import { atom, selector, useRecoilState } from "recoil";

const fahrenheit = atom({
  key: "fahrenheit",
  default: 32
});

const celcius = selector({
  key: "celcius",
  get: ({ get }) => ((get(fahrenheit) - 32) * 5) / 9,
  set: ({ set }, newValue) => set(fahrenheit, (newValue * 9) / 5 + 32)
});

function TempCelcius() {
  const [tempF, setTempF] = useRecoilState(fahrenheit);
  const [tempC, setTempC] = useRecoilState(celcius);

  const addTenCelcius = () => setTempC(tempC + 1);
  const addTenFahrenheit = () => setTempF(tempF + 1);

  return (
  <div>
    Temp (Celcius): {tempC} Temp (Fahrenheit): {tempF} 
   <button onclick="{addCelcius}">Add 1 Celcius</button> 
   <button onclick="{addFahrenheit}">Add 1 Fahrenheit</button> 
  </div>
)
Enter fullscreen mode Exit fullscreen mode

What is useRecoilState?

As you may have seen in the above code examples, useRecoilState is almost identical to the useState React hook. It returns the value, and the setter for a piece of state.

const [state, setState] = useRecoilState(atomName);
Enter fullscreen mode Exit fullscreen mode

Use state within a component as the value, and use the setState function to set the state of the Atom.

Simple, concise and easy to set up.

What is useRecoilValue?

useRecoilValue gets the current state of an Atom and allows a component to subscribe to that state. When the Atom updates, the useRecoilValue gets that state and passes it through.

const state = useRecoilValue(atomName);
Enter fullscreen mode Exit fullscreen mode

This allows components that do not require the ability to set an Atoms state to use the state with no added overhead.

Overview

Recoil sounds like it is set to be incredibly helpful in app development. The ability to easily set and get state, as well as share it across an application quickly looks very appealing. I will personally be holding back to see how it fairs in production, and which way the Open Source community takes it.

For more information on usage, and the other hooks – take a look at https://recoiljs.org/

Top comments (0)