State Management on React [Part 3] - Jotai
Tags: react, javascript, typescript, frontend
Published: 2023-05-31 22:45:30

Sup people! How are you doing? Are you ok?
Is a pleasure to see you again!
This is the third part of articles of react management, wow!

I hope you guys liked the previous article where I talk about state management using the **Redux** with **redux tooltik**. Now we will create the same application, but using **Jotai** 👻. We are going to create a simple application but we will be able to see the code of the technologies and compare the implementation.

The meaning of the Jotai in japanese is... guess?
Jotai 状態 means **State**

I'll cover these technologies in each article:

- [**Context API (part 1)**](https://dev.to/kevin-uehara/state-management-on-react-part-1-context-api-4jig)
- [**Redux (part 2)**](https://dev.to/kevin-uehara/state-management-on-react-part-2-redux-n5f)
- [**Jotai (part 3)**](https://dev.to/kevin-uehara/state-management-on-react-part-3-jotai-i7f)
- [**Recoil (part 4)**](https://dev.to/kevin-uehara/state-management-on-react-part-4-recoil-55mp)
- [**Zustand (part 5)**](https://dev.to/kevin-uehara/state-management-on-react-part-5-zustand-1jl3)

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

## Introduction

According to the documentation of Jotai:

> Jotai takes an atomic approach to global React state management with a model inspired by Recoil.

> Build state by combining atoms and renders are automatically optimized based on atom dependency. This solves the extra re-render issue of React context and eliminates the need for memoization.

> It scales from a simple useState replacement to an enterprise TypeScript application with complex requirements. Plus there are plenty of utilities and integrations to help you along the way!

Sooo yeah! Jotai is inspired on **Recoil**, for coincidence (or not) will be the part 4. But let's see the similarities of this libraries in the next part.

Jotai offers a minimal API to we manage our state in application, with many utilities and integrations. This library is so simple that I don't have so much say, 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 jotai
```

**Wait, what? just that?** 🤔 
yup! we only need the jotai dependency.

Let's start adding the **Provider** of jotai on our main three of components. I just renamed the Provider as you can see on import, just not to confuse. But you can import just as `Provider` from `jotai`

### main.tsx

```tsx
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.tsx";
import "./index.css";
import { Provider as JotaiProvider } from "jotai";
import { ButtonChangeTheme } from "./components/ButtonChangeTheme/index.tsx";
import { Content } from "./components/Content/index.tsx";

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

Now we can use the hooks that the Jotai offers to us...

I will create a directory on `/src` called `atoms` 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:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5qdxzv6flhtes0ro6awj.png)

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

```ts
import { atom } from "jotai";

export const isDark = atom(false);
export const changeTheme = atom(null, (get, set) => {
  set(isDark, !get(isDark));
});
```

**AND THATS'S JUST IT!**

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j9nasukgf8tavfrz2y3g.gif)

But before we create the todo, let's talk about the concept of atoms. 

Atoms we can think as a "piece" of state. It is very similar to useState.
According of the documentation:

> The atom function is to create an atom config. We call it "atom config" as it's just a definition and it doesn't yet hold a value. We may also call it just "atom" if the context is clear.

> An atom config is an immutable object. The atom config object doesn't hold a value. The atom value exists in a store.

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

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

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

```ts
export interface Todo {
  id: number;
  label: string;
  done: boolean;
}
```

I will create a file on `store.ts` and the code will be:

```tsx
import { atom } from "jotai";
import { Todo } from "./types";

export const removeTodo = (todos: Todo[], id: number): Todo[] =>
  todos.filter((todo) => todo.id !== id);

export const addTodo = (todos: Todo[], text: string): Todo[] => [
  ...todos,
  {
    id: Math.max(0, Math.max(...todos.map(({ id }) => id))) + 1,
    text,
    done: false,
  },
];

//Jotai
export const newTodoAtom = atom("");
export const todos = atom<Todo[]>([]);

export const addTodoAtom = atom(null, (get, set) => {
  set(todos, addTodo(get(todos), get(newTodoAtom)));
  set(newTodoAtom, "");
});
export const removeTodoAtom = atom(null, (get, set, id: number) => {
  set(todos, removeTodo(get(todos), id));
});
```

First atom it will store the todo that we will type and the second it will store our todos items.

The `addTodoAtom` and `removeTodoAtom` it will be atoms the "update" the store of todos. But remember that we always be working as immutability as you can see on functions above.

I create that functions to facilitate the visualization of our atoms and to become more visible and lean what we are doing.

Notice that both `addTodoAtom` and `removeTodoAtom` are using as second parameter the `get`, `set` and `update (that can be any value which we can pass as parameter)`. The **get** and **set** we can pass the atom that we will updating.

And we finish the state management! Fast and simple, isn’t it?

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

First, let's change the `ButtonChangeTheme`:

### components/ButtonChangeTheme/index.tsx

```tsx
import { useAtom } from "jotai";
import button from "./button.module.css";
import { changeTheme } from "../../atoms/theme/store";

interface ButtonChangeThemeProps {
  label: string;
}

export const ButtonChangeTheme = ({ label }: ButtonChangeThemeProps) => {
  const [, changeColor] = useAtom(changeTheme);

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

We will use the `useAtom` to get the atom of change theme. Remember when I said that the atom is very similar with useState. And when we created the atom of `changeTheme` we pass null as first parameter. So we are working with the "set" of the "useState".

Now changing the `Content` dummy component:

### components/Content/index.tsx

```tsx
import { useAtom } from "jotai";
import { isDark as isDarkState } from "../../atoms/theme/store";

interface ContentProps {
  text: string;
}

export const Content = ({ text }: ContentProps) => {
  const [isDark] = useAtom(isDarkState);

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

Now we are using the atom to get the theme.

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:

### components/FormTodo/index.tsx

```tsx
import style from "./Form.module.css";
import { Button } from "../Button";
import { Input } from "../Input";
import { useAtom } from "jotai";
import { addTodoAtom, newTodoAtom } from "../../atoms/todo/store";

export const FormTodo = () => {
  const [newTodo, setNewTodo] = useAtom(newTodoAtom);
  const [, setAddTodo] = useAtom(addTodoAtom);

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

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 { useAtom } from "jotai";
import style from "./ListTodo.module.css";
import { removeTodoAtom, todos as todosStore } from "../../atoms/todo/store";

export const ListTodo = () => {
  const [todos] = useAtom(todosStore);
  const [, setRemoveTodo] = useAtom(removeTodoAtom);

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

### AND WE FINISHED, EASY PEASY, ISN'T IT?

## Results

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

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/acua6ti3ac90v1pw2urg.gif)

And the React Dev Tools Profiler:

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

# Conclusion

Jotai offers a minimal API to manager our state. It simple and easy to maintain our state. Also, works with Next.js, Gatsby, Remix, and React Native.

Remember of the concept of atoms, because we will use this same concept on Recoil (library that Jotai was inspired).

I'm not saying that jotai 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.

Jotai, also offers some utils packages, so if you are interested just access the documentation.

![Jotai Documentation image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/363hk5q5mhqt555l320t.png)

So in summary, in this article we saw how we can implement the jotai, creating atoms and useAtoms to manipulate our global state.

Some references:

- [Jotai](https://jotai.org/docs/introduction)
- [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 parts! 💜