Jotai's Code Explanation

Jotai's Code Explanation

Hi. I hope that you like it

Today Let's learn how to use Jotai in a basic usage and keyway, In a previous article Jotais Introduction basic concepts.

Aclaration: I'm not using providers, contexts or redux for this example. Jotai is state management outside of the render

Atom

We need to declare an atom with an initial value primitive as Strings, Arrays, Booleans, Objects, and Nulls.

In React.js, This atom is placed outside of the render. This is great because we can use this atom in others atoms and read or write the atom. With only importing the variable

If you do not know what is the mean of the atom, I recommend reading the introduction Jotais

import { atom } from 'jotai'

export const NAME_ATOM = atom("Inital Value") 
//Strings, Arrays, Booleans, Objects, Nulls.

Ok, But how can I read the value or change the value in the render? Well, We have 3 essential hooks for consuming the atoms.

UseAtom

The useAtom hook returns the atom value and an update function as a tuple, just like React's useState. It takes an atom config created with atom().

It's the typical useState but with more improvements

import { useAtom } from "jotai";

const MyComponent = () => {
  const [value, setValue] = useAtom(NAME_ATOM)
  return ....
}
export default MyComponent

UseAtomValue

UseAtomValue hook only returns the value of the atom.

import { useAtomValue} from "jotai";

const MyComponent = () => {
  const name = useAtomValue(NAME_ATOM);
  return ....
}
export default MyComponent

UseSetAtom

Sometimes we need to update the state of the atom. but we do not need to know the value

const MyComponent = () => {
 const [, setName] = useAtom(NAME_ATOM)
  return ....
}
export default MyComponent

This is wrong because we are rendering the component but we do not use the value. So the useSetAtom avoids rendering unnecessaries

import { useSetAtom } from "jotai";

const MyComponent = () => {
  const setName = useSetAtom(NAME_ATOM)
  return ....
}
export default MyComponent

If you are interested in how works that hook, I recommend reading the official Jotai documentation

Atom Getter or Reader

The atom receives a primitive value or a function. This function is the first method getter. You can only read atom values and create async fetch data

import { atom } from "jotai";
import { atomWithDefault } from "jotai/utils";

export const FETCHUSERS_ATOM = atomWithDefault(async () => {
  const fetching = await fetch("https://jsonplaceholder.typicode.com/users");
  const result = await fetching.json();
  return result as User[];
});
const ReadfetchAtom = atom((get) => {
  return { 
    users:get(FETCHUSERS_ATOM),
    author:get(NAME_ATOM)
  }
});

In this case, we are using atomWithDefault because is a function to create a resettable primitive atom. Its default value can be specified with a read function or async function instead of a static initial value.

And atom with a getter function. we return the data of FETCHUSERS_ATOM with the function get

FETCHUSERS_ATOM is a fetching data to JSONPlaceholder and returns a list of users. We can use this atom with the Jotai hooks. but in this case, I'm consuming the data in another atom.

REMEMBER!

When you are working with async atoms. Use the suspense component of react.js recommended by the official documentation Jotai Async

Atom Getter but with Setter and Arguments

With this option, you can declare atoms to set other atoms and read them.

For example, if I have a to-do list, and I need to delete only one, I declare an atom only to set the main atom.

But why do I do not that in the render?

Because when I add more to-do's I'm going to render the component. and that is wrong.

type TodoListProps = {
  id: string;
  title: string;
};

type DeleteProps = {
  id: string;
};

export const TODOLIST_ATOM = atom([] as TodoListProps[]);

///////////////////////////////////////////////////////

const DELETEATOM = atom(null, (get, set, args: DeleteProps) => {
  const todos = get(TODOLIST_ATOM);
  set(
    TODOLIST_ATOM,
    todos.filter((item) => item.id !== args.id)
  );
});

We have a TodoList with a default array atom. and have a setter delete atom, we call the todo list we can filter the array with the id to delete an item.

Other examples.

const RESET_ATOMS = atom(null, (get, set) => {
  set(TODOLIST_ATOM, []);
  set(FETCHUSERS_ATOM, []);
  set(NAME_ATOM, "Default Name");
  set(IMAGE_ATOM, URL_DEFAULT);
});
////// RENDER ////
const setAtoms = useSetAtom(RESET_ATOMS);

REMEMBER!

Your atom only works with the 3 methods.

  1. Read

  2. Read and Write

  3. Write

If your atom is setter other atoms you can't use the value or if your atom is only read you can't set the atom in that atom.

This is a basic example of using atoms. Exist a lot more examples in the official documentation and use cases. I recommend reading the documentation.

If you are interested in the example. I have created an example using Lucy Nxtjs, Jotai and Vite.

Github Repository

URL Page Web Example

Sources:
Jotai
Daishi Kato

If you are interested follow me.

Github

Linkedin