loading...

Using Recoil With React

iamawaisakram profile image Awais Akram Mughal ・2 min read

A new State Management Library for React

If you would like to learn more about its need and the thought process behind it. Kindly go to: Recoil Home Page and watch the video at the bottom of the page.

Introduction:

Firstly:
The basic use of Recoil is through the introduction of Atom.

import { atom } from 'recoil'

export const DataEntriesAtom = atom({
  key: 'dataEntries', // * unique Key (with respect to other atoms/selectors)
  default: [] // * default value (aka initial value)
})

The code is self explanatory with comments.

Here's how you use it in the component.

import React from 'react'
import { useRecoilState } from 'recoil'
import moment from 'moment'

// * Atoms
import { DataEntriesAtom } from '../../Recoil/Data/Atoms'

// * Style
import './index.css'

export default props => {
  const [logbookEntries, setLogbookEntries] = useRecoilState(DataEntriesAtom)

  return (
    <div id='logbook'>
      <div className='title-div'>
        <p className='title'>Logbook</p>
      </div>
      <div className='logbook-result'>
        {logbookEntries.map(entry => (
          <div className='entry' key={entry.id}>
            <p className='date'>
              {moment(entry.createdAt).format('MMMM Do YYYY')}
            </p>
            <div className='value'>{entry.value}</div>
          </div>
        ))}
      </div>
    </div>
  )
}

But What is the use of the Atom you ask?
If you're using the DataEntriesAtom in any other component and you call the setLogbookEntries from this component, Recoil monitors the change in that particular atom and only re-renders the component that is using this Atom. Simple yet efficient.

It reduces the boilerplate code that you have to write and let's say you have a DOM tree with two main branches that have no link to one another, but you want a node of the separate branch to change its value as soon as you change the value of the current branch.

While using redux, you would have to write a lot of code to get this working. But in this case, just defining an atom with get it working. :)

Also, Notice that we are using useRecoilState imported from Recoil.

Secondly:
Recoil Introduced Selector.

import { selector } from 'recoil'

// * Atom
import { DataEntriesAtom } from './Atoms';

// * API calls
import {
  GetDataEntriesAPI
} from '../../Api/Data'

export const GetDataEntriesQuery = selector({
  key: 'dataEntriesQuery',
  get: async ({ get }) => {
    let previousEntries = get(DataEntriesAtom);
    let entries = await GetDataEntriesAPI()

    return previousEntries.concat(entries)
  }
})

Selectors represent derived state. You can think of derived state as the output of passing state to a pure function that modifies the given state in some way.

Let's Setup Recoil:

In you Parent JS File(In my case it's the index.js)

For Asynchronous calls: you can use Suspense, on calling the selector, Recoil will manage the loading of the Component for you.

import React from 'react'
import ReactDOM from 'react-dom'
import { RecoilRoot } from 'recoil'

// * Routes
import Routes from './Routes'

// * Styling
import './index.css'

ReactDOM.render(
  <React.StrictMode>
    <RecoilRoot>
      <React.Suspense fallback={<div>Loading...</div>}>
        <Routes />
      </React.Suspense>
    </RecoilRoot>
  </React.StrictMode>,
  document.getElementById('root')
)

Discussion

pic
Editor guide