RecoilJS Video Tutorial


In this tutorial, I invite you to discover RecoilJS, a library that allows you to create a state shared between several components.

Before embarking on the discovery of yet another library, it is important to see the limitations of existing solutions.

Contexts

Contexts are the first avenue to explore when we want to share a state. They are practical but it is necessary to create a new provider for each new context. Which can quickly become complex.


  
    
      
    
  

Likewise, it is not possible to add new contexts on the fly because we are constrained by the structure of our elements.

Redux

Redux is suitable for creating a centralized state that can then be consumed by child components. However, its architecture can be heavy for simple cases. and as for contexts, it is not possible to create new states on the fly (without having recourse to an array which memorizes the state of each component).

RecoilJS to the rescue.

The recoil approach is much simpler and allows you to share states, named atom, simply. As for Redux we will surround our application with a root component.

import React from 'react'
import {RecoilRoot} from 'recoil'

function App () {
  return (
    
      
    
  
  )
}

Then we will be able to create a atom, which will be a piece of state which will be external to the structure of our application and which can then be consumed by different components.

export const counterState = atom ({
  key: 'counterState', // unique ID ID
  default: 0 // Initial state
})

This state can then be consumed by any component.

import React from 'react'
import {useRecoilState} from 'recoil'
import {counterState} from './atoms/compteurState'

function Counter () {
  const (counter, setCounter) = useRecoilState (counterState)

  const increment = () => {
    setCounter (n => n + 1)
  }

  return 
}

All the counters will share the same state whatever their position in the structure of our application. You can also simply recover this state without necessarily modifying it.

function CounterText () {
  const counter = useRecoilValue (counterState)

  return 

Counter {counter}

}

It is also possible to create selectors that allow you to retrieve values ​​derived from an atom.

const charCountState = selector ({
  key: 'charCountState',
  get: ({get}) => {
    return get (textState) .length
  }
})

It is then possible to consume these selectors as one would with an atom.

function CharacterCount () {
  const count = useRecoilValue (charCountState)

  return <> String size: {count}
}

You also have the possibility to create atoms on the fly thanks to a parameter. For example, we want to create several synchronized counter.

const counterStateFamily = atomFamily ({
  key: 'familyCounter',
  default: 0
})

Each counter will then be assigned an ID and can generate a new atom on the fly.

function ElementListItem ({elementID}) {
  const counter = useRecoilValue (counterStateFamily (elementID))
  return 

Counter {counter}

}

Still experimental

This approach is still experimental but part of the API is already stabilized.
The main problem with this approach at the moment is memory optimization (a family of atoms can generate a fairly large number of states which will not necessarily be freed later).