State Management on React [Part 4] - Recoil
Tags: typescript, react, javascript, frontend
Published: 2023-06-04 23:21:35

Whaaats up, people! It's nice to have you here again!!!

![The office happy gif](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5mifwe80xfwct2i3or3i.gif)

This is the fourth and penultimate part of articles of react management. How are you feeling with so much technologies? Amazing, isn’t it?
we are almost at the end of our journey!

I hope you guys liked the previous article where I talk about state management using the Jotai 👻. I bring the concept of atoms and selectors and this will be very important for this article. Because, Jotai was inspired by Recoil, so the same concepts of atoms we will use here.

If you did not saw the previous part you can find here: [Jotai State Management](https://dev.to/kevin-uehara/state-management-on-react-part-3-jotai-i7f)

We are going to create a simple application but we will be able to see the code of the technologies and compare the implementation.

Just to remember, let's get situated:

- **Context API (part 1)**
- **Redux (part 2)**
- **Jotai (part 3)**
- **Recoil (part 4)**
- **Zustand (part 5)**

**Summary:**
- [**Introduction**](#introduction)
- [**Show me the code**](#show-me-the-code)
- [**Results**](#results)
- [**Conclusion**](#conclusion)

## Introduction

According to the documentation of [Recoil](https://recoiljs.org/):

> Recoil defines a directed graph orthogonal to but also intrinsic and attached to your React tree. State changes flow from the roots of this graph (which we call atoms) through pure functions (which we call selectors) and into components.


![Image of benefits of recoil](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zxjtic78nn08i4l4twek.png)

Recoil provide the minimal and simple API's to we manage our state (remember some other state manager cof cof jotai). This library is so simple that I don't have so much say aaas Jotai, so let's implement and I will cover some concepts beyond we code.

Just to remember again, if you did not saw the first part, I created all components that we will use in this and next parts on the first part. Soooo if you did not saw yet, I recommend to see on: [State Management on React [Part 1] - Context API.](https://dev.to/kevin-uehara/state-management-on-react-part-1-context-api-4jig)

We will use the first version of the components that we created without the Context API integration.

Now with all concepts at hands, LET'S TO THE CODE!

## Show me the code

Let's add the dependencies that we will use:

```sh
yarn add recoil
```

Yeah, easy peasy!

Let's start adding the **Provider** of recoil, called `RecoilRoot` on our main three of components.

### main.tsx

```tsx
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.tsx";
import "./index.css";
import { RecoilRoot } from "recoil";
import { ButtonChangeTheme } from "./components/ButtonChangeTheme/index.tsx";
import { Content } from "./components/Content/index.tsx";

ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
  <React.StrictMode>
    <RecoilRoot>
      <ButtonChangeTheme label="Change Theme" />
      <Content text="Hello World!" />
      <App />
    </RecoilRoot>
  </React.StrictMode>
);
```

I will create a directory on `/src` called `store` and for each feature I will create a folder with the name of the feature. So, we have two features in our app: change theme color (dark mode) and a todo list:

![Directory our project image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hub580ziibpb5o4txii0.png)

I will start with the dark mode feature. We will create a file on `store/theme/index.ts` and create this code:

```tsx
import { atom } from "recoil";

export const isDarkState = atom({
  key: "IsDark",
  default: false,
});
```

That's it! What?
Yes! Minimalistic and simple.

We will provide a key and the value of the atom. But we will we see soon, that it's not so simple and there's magic here. We need to manipulate this state.

Now let's see how the todo store will it be.

Let's create on` store/theme` two files. First the types types.ts (my preference) and the index.ts.

The types.ts contains just the type of our todo:

```tsx
export interface ITodo {
  id: number;
  text: string;
  done: boolean;
}
```
I will create a file on index.ts and the code will be:

```tsx
import { atom } from "recoil";
import { ITodo } from "./types";

export const todoListState = atom<ITodo[]>({
  key: "TodoList",
  default: [],
});
```

Woww, simple we created our "store" files using the atoms. Notice, that de default value it's an array, because we will provide a list o todo items.

Now we will change the components to use our states and atoms.

First, let's change the ButtonChangeTheme:

### components/ButtonChangeTheme/index.tsx

```tsx
import { useSetRecoilState } from "recoil";
import button from "./button.module.css";
import { isDarkState } from "../../store/theme";

interface ButtonChangeThemeProps {
  label: string;
}

export const ButtonChangeTheme = ({ label }: ButtonChangeThemeProps) => {
  const setChangeColor = useSetRecoilState(isDarkState);

  const handleChangeColor = () => {
    setChangeColor((color) => !color);
  };

  return (
    <button className={button.btn} onClick={handleChangeColor}>
      {label}
    </button>
  );
};
```

Here, we have the first difference of jotai. Recoil will provide a hook to set the state, called `useSetRecoilState`, where we will pass the atom that we created. And the **business rules it will be stay on component**.

Now changing the `Content` dummy component:

### components/Content/index.tsx

```tsx
import { useRecoilValue } from "recoil";
import { isDarkState } from "../../store/theme";

interface ContentProps {
  text: string;
}

export const Content = ({ text }: ContentProps) => {
  const isDark = useRecoilValue(isDarkState);

  return (
    <div
      style={{
        height: "30vh",
        width: "100vw",
        color: isDark ? "#fff" : "#111827",
        backgroundColor: isDark ? "#111827" : "#fff",
      }}
    >
      {text}
    </div>
  );
};
```

To use the state, Recoil will provide the hook `useRecoilValue` and we will pass the atom that we created.

Our `FormTodo` component, let's just use the atoms that we created to store the todo that we type and add a new todo item. But again, the business logic will stay on component:

### components/FormTodo/index.tsx

```tsx
import style from "./Form.module.css";
import { Button } from "../Button";
import { Input } from "../Input";
import { useState } from "react";
import { useSetRecoilState } from "recoil";
import { todoListState } from "../../store/todo";
import { ITodo } from "../../store/todo/types";

export const FormTodo = () => {
  const [todo, setTodo] = useState("");
  const setTodoState = useSetRecoilState(todoListState);

  const handleAddTodo = () => {
    const newTodo: ITodo = {
      id: Math.random() * 1000,
      text: todo,
      done: false,
    };

    setTodoState((state) => [...state, newTodo]);
    setTodo("");
  };

  return (
    <div className={style.formContainer}>
      <Input
        value={todo}
        label="Todo"
        onChange={(evt) => setTodo(evt.target.value)}
      />
      <Button label="Add" onClick={handleAddTodo} />
    </div>
  );
};
```

To store the value of input value I will be using the `useState`. And to add on todo list we will copy the state, using the spread operator and call the hook `useSetRecoilState`.

And finnaly, let's change the `ListTodo` component to use the atom to remove a todo item and retrieve the todos:

### components/ListTodo/index.tsx

```tsx
import { useRecoilValue, useSetRecoilState } from "recoil";
import style from "./ListTodo.module.css";
import { todoListState } from "../../store/todo";

export const ListTodo = () => {
  const todos = useRecoilValue(todoListState);
  const setTodoState = useSetRecoilState(todoListState);

  const handleRemoveTodo = (id: number) => {
    const removed = todos.filter((todo) => todo.id !== id);
    setTodoState(removed);
  };

  return (
    <ul>
      {todos.map((todo) => (
        <li className={style.item} key={todo.id}>
          <label>{todo.text}</label>
          <i
            className={style.removeIcon}
            onClick={() => handleRemoveTodo(todo.id)}
          />
        </li>
      ))}
    </ul>
  );
};
```

Here, we are using both hooks that I introduced to you `useRecoilValue` to get the todoList and `useSetRecoilState` to set the new list with the todo item removed.

and we finish one more time the same app LOL!

## Results

Now we can see how we use Recoil, offering the minimum API to manage our state in a exact manner, without unnecessary re-renders.

But what I introduced to you it's just the basic of recoil. Read the [documentation](https://recoiljs.org/docs/introduction/getting-started) to see more details: 

The visual will not change but let's see 👀 using the React Dev Tools with highlighting render:

![Highlight of component rendering gif](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/260qbdttr5qttbcdfns4.gif)

And the React Dev Tools Profiler:

![Profile viewer record of components rendering gif](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9fsyy39wfgov071bhygc.gif)

## Conclusion

Recoil offers a minimal API to manager our state. It simple and easy to maintain our state.

It's easy to see jotai's inspiration

I'm not saying that recoil is the best library and that you should use it in your project. So much so that the purpose of these articles is to compare the application and implementation of each state manager.


![Recoil Documentation image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7b13bdwh5ah15kwwquxr.png)


So in summary, in this article we saw how we can implement the recoil, creating atoms and manipulate our global state using the hooks that the recoil provides.

Some references:

- [Recoil](https://recoiljs.org/)
- [My repository](https://github.com/kevinuehara/react-state-management)
- [Linkedin](https://www.linkedin.com/in/kevin-uehara/)

That's all folks!

I hope you enjoyed it and added some knowledge. See you in the next and last part, where we will talk about Zustand! 💜