Getting started with React Recoil

18th May 2020

Getting started with React Recoil

Recoil is a state management library for React by facebook.

Overview

Recoil lets you create a data-flow graph that flows from atoms (shared state) through selectors (pure functions) and down into your React components. Atoms are units of state that components can subscribe to. Selectors transform this state either synchronously or asynchronously

note TLDR Atom: Single value/state/object.

atom = x || { x: any } || []

Selector: Derived/Computed value based on an atom's current value or another selector value.

selector = someFunction(atom) || someFunction(anotherSelector)

Installation

yarn add recoil

Create an atom

Let's start with creating an atom which holds an input number. Since an atom is a global value, it requires a unique key.

import { atom } from 'recoil'

export const inputNumberAtom = atom({
  key: 'inputNumberAtom',
  default: 0,
})

Create selectors

Now we have an atom, let's create two selectors which uses the previously defined atom. Since selectors are global values, each one requires a unique key.

import { selector } from 'recoil'
import { inputNumberAtom } from './atom'

export const addTenSelector = selector({
  key: 'addTenSelector',
  get: ({ get }) => {
    return get(inputNumberAtom) + 10
  },
})

export const squareOfAddTenSelector = selector({
  key: 'squareOfAddTenSelector',
  get: ({ get }) => {
    const addTenVal = get(addTenSelector)
    return addTenVal * addTenVal
  },
})

Final App

Now let's move on to creating our app using recoil.

import React from 'react'
import { RecoilRoot, useRecoilState, useRecoilValue } from 'recoil'
import { inputNumberAtom } from './atom'
import { addTenSelector, squareOfAddTenSelector } from './selector'

const PrimaryComponent = () => {
  const [inputNumber, setInputNumber] = useRecoilState(inputNumberAtom)
  const addTenValue = useRecoilValue(addTenSelector)
  const squaredValue = useRecoilValue(squareOfAddTenSelector)

  const onChange = React.useCallback((event: any) => {
    setInputNumber(event.target.value)
  }, [])

  return (
    <div>
      <h2>PrimaryComponent</h2>
      <input type="number" onChange={onChange} value={inputNumber} />
      <h4>inputNumber = {inputNumber}</h4>
      <h4>addTenSelector = {addTenValue}</h4>
      <h4>squareOfAddTenSelector = {squaredValue}</h4>
    </div>
  )
}

const SecondaryComponent = () => {
  const inputNumber = useRecoilValue(inputNumberAtom)
  const addTenValue = useRecoilValue(addTenSelector)
  const squaredValue = useRecoilValue(squareOfAddTenSelector)

  return (
    <div>
      <h2>SecondaryComponent</h2>
      <h4>
        Since recoil offers global state. This component will receive the state
        updates as well{' '}
      </h4>
      <h4>inputNumber = {inputNumber}</h4>
      <h4>addTenSelector = {addTenValue}</h4>
      <h4>squareOfAddTenSelector = {squaredValue}</h4>
    </div>
  )
}

export default () => {
  return (
    <RecoilRoot>
      <div>
        <PrimaryComponent />
        <hr />
        <SecondaryComponent />
      </div>
    </RecoilRoot>
  )
}

If you had followed this tutorial, now your app will look like this. Try changing the input number and see the selectors and atoms in action.!