ReactJS: State Persistence Using Recoil
Tags: javascript, react, tutorial, recoil
Published: 2022-02-24 06:07:03

[Recoil](https://github.com/facebookexperimental/Recoil) is an open-source experimental state management library by Facebook. It's one of the many libraries that makes managing states easier like persisting the theme state (light/dark mode) of your website. Other examples of such libraries are Xstate, Redux, Zustand, and Jotai.

##  Getting Started

In your project, install Recoil using the npm command below.

```shell
npm install recoil
```

or if you're using yarn.

```shell
yarn add recoil
```

You can view more installation guides in the documentation [here](https://recoiljs.org/docs/introduction/installation).

Next, we need to add Recoil to our `index.js` so that we can use it everywhere in our project.

```javascript
...
import { RecoilRoot } from "recoil";

ReactDOM.render(
  ...
    <RecoilRoot>
        <AppRoutes />
    </RecoilRoot>
  ...
  document.getElementById('root')
);
```

## Creating an atom

Atoms contain the source of truth for our application state and below is an example of creating an atom.

```javascript
export const darkModeState = atom({
  key: 'darkMode',
  default: false,
});
```

For use cases like this, I like to put my atoms inside a `globalState.js` file inside the shared folder of my project. This is because many components will share this atom. Moreover, inside the atom that I made is a unique key and a default value. An atom key is a serializable value that labels the atom and it's useful especially when we want to persist our state. On the other hand, the default value is the default state of the atom.

Using the atom in your component is almost similar to useState hooks.

```javascript
const [isDarkModeEnabled, setIsDarkModeEnabled] = useRecoilState(darkModeState);
```

Instead of `useState`, we use `useRecoilState` and instead of passing the default state, e.g., false, we pass in our atom, i.e., `darkModeState`.

When we don't need to change the state of the atom and only need access to its value, we can simply do it like the code snippet below.

```javascript
const isDarkModeEnabled = useRecoilValue(darkModeState);
```

## Saving the state to local storage

There are use cases when we want to keep states like saving the preferred theme to the website visitor's browser local storage. This helps returning visitors to keep their preferred settings that they set on their previous visit.

Below is an example of using Recoil to persist the theme of a website.

```javascript
const localPersist = ({onSet, setSelf, node}) => {
  const storedData = localStorage.getItem(node.key)
  if (storedData != null){
    setSelf(JSON.parse(storedData))
  }
  onSet((newData, __, isReset) => {
    isReset
      ? localStorage.removeItem(node.key)
      : localStorage.setItem(node.key, JSON.stringify(newData));
  })
}

export const darkModeState = atom({
  key: 'darkMode',
  default: false,
  effects: [localPersist]
});
```

Notice the `effects` parameter that I added to my atom. That parameter is called [atom effects](https://recoiljs.org/docs/guides/atom-effects/) and it's an API for managing side-effects and synchronizing or initializing Recoil atoms. It's typically used in state persistence, synchronization, managing history, etc. As seen above, I passed the function that handles saving, removing, and getting the state from the browser's local storage

Furthermore, the `localPersist` function can be called by any atom. In other words, if you need a state to persist, you can just call the function to persist your state. Besides boolean values, the function also works for other data types like strings, objects, and arrays.

```javascript
export const myStringState = atom({
  key: 'myString',
  default: '',
  effects: [localPersist]
});

export const myListState = atom({
  key: 'myList',
  default: [],
  effects: [localPersist]
});
```

Inside the `localPersist` function we have the `onSet` function which gets called when our atom changes. To get the state from our local storage, we use the `setSelf` function. Moreover, the `isReset` function is used when the `useResetRecoilState` is called which removes the state from the browser's local storage.

Now that we've finished setting up the `globalState.js`, we now have states that are accessible to multiple components which also persists. You can check if it works by going to `inspect element > Application tab > Storage > Local Storage > http://your-website-url`.

## Final Thoughts

Recoil is easy to implement and as seen earlier, it's similar to how we use `useState`. There are many new state management libraries currently existing and maybe more will be released. Jotai is an example of a state management library that is similar to Recoil–they are both atomic. Other types of libraries are flux (Redux, Zustand) and proxy (Mobs, Valtio, Overmind). At the end of the day, choosing the right library for your project depends on many variables like package size, use case, and more.

<hr/>

[Click here](https://github.com/joiellantero/react-recoil-demo) to view a sample implementation of what we've discussed.