Jotai - Perhaps the simplest drop-in state manager yet | Daniel.Me

Jotai - Perhaps the simplest drop-in state manager yet

Date: October 2nd, 2021

Jotai is a primitive state manager for React, and provides enough flexibility for those who are looking for a drop-in replacement of the Context API. I recently began switching my Teachery project from Apollo Client to Jotai. Apollo client state manager has quite a few nagging bugs that convinced me to find a lightweight state manager to handle local state, while Apollo client continues to handle GraphQL queries.

To install Jotai into your React application run the below command which also will install some peer dependencies. You can also use npm if you prefer, and if you are using React Native, replace react-dom with react-native.

yarn add jotai react scheduler react-dom

Jotai is very similar to Recoil, an experimental state manager from Facebook. A couple benefits are it's barebones API, no string keys required, and the state manager is written in TypeScript, and is useful for any Typescript project, but still works fine in a vanilla Javascript React project.

Just like Recoil, Jotai represents a piece of state with the term 'atom'. An atom can be a primitive value such as a number or boolean, as well as taking in an object or array. Unlike Recoil, you don't need to define a key, which makes Jotai atoms easier to use.

import { atom } from "jotai";

export const successAlertAtom = atom(false);
export const count = atom(0);
export const modalAtom = atom({
  toggleOn: false,
  modalId: 0,
  target: null,
  editImg: false,
});

Because you setup the Provider in the root of your app, you can use your atoms anywhere, using a React-like hook called useAtom that looks awfully like the useState hook. It can be used to set state, or be used read-only/write-only. In my Teachery project, I used them to control the opening and closing of modals in my project, and for alerts. Here's an example with the object modal seen in the above figure to toggle a modal off (by pressing the close button or clicking outside of the modal)...

import { useAtom } from "jotai";

  const [modal, setModal] = useAtom(modalAtom);
  const { toggleOn, modalId, target, editImg } = modal;

  const toggleOffModal = () => {
    setModal((atom) => (atom = { ...atom, toggleOn: false, editImg: false }));
  };

As you can see they are very easy to destructure and reuse without the need for boilerplate like you would be dealing with in Redux or even with the Context API.

You can also combine atoms to make what are called derived atoms. Here's an example taken from the official docs...

const count1 = atom(1)
const count2 = atom(2)
const count3 = atom(3)

const sum = atom((get) => get(count1) + get(count2) + get(count3))

For Typescript users, primitive and derived atoms are type inferred, but you can define them explicitly if required. The beauty of Jotai being written in Typescript makes defining atoms as simple as could be. When you use the useAtom hook, the types are based on your atom types without needing to define any additional props or interfaces.

const booleanAtom = atom<boolean>(false)
const arrayAtom = atom<number[]>([3, 5, 7])

Menu