Jotai: An Atomic Model State Management Library
Jotai is a state management library that is built on the Atomic Model for state management, and is a bit exotic when compared to the other state managers we've seen over the past decade with React.
Introducing the Atomic Model
In the atomic model, atoms represent distinct pieces of state that can be directly mutated.
For our ecommerce example, we would have atoms for cart and reviews.
Then for an average rating atom, we would have it depend on the reviews atom to make its calculation.
Think of the atomic model as being similar to a spreadsheet where cells interact through equations: when one cell changes, the others update automatically, eliminating the need for dependency arrays or manual recalculations.
Using Jotai to Create Atoms
Intially Jotai atoms were defined globally, but now we are able to create a store and provide it using a store provider.
Each store can have instances of particular atoms, and there can either be multiple stores throughout the hierarchy or a single store at the top of the hierarchy.
For this exercise, we'll use the single store approach. We will have the provider at the top of the layout and the atoms will go down the tree.
Challenge
The objective of this exercise is to remove the existing React cart context and replace it completely with Jotai.
To do this, you'll need to remove the existing CartContext
object and replace it with a Jotai store. Then use atoms to model the cart and reviews.
As before, you cannot safely use a Jotai atoms declared globally!
After you add jotai
to the project, you'll be ready to create the atoms.
Here's an example of how to create an atom:
import { atom } from "jotai";
export const countAtom = atom<number>(0);
You can create a Jotai "store" for atoms using createStore
. Here is an example provider that uses Jotai's Provider
to pass the store around:
"use client";
import { useState } from "react";
import { createStore, Provider } from "jotai";
const StoreProvider = ({ children }: { children: React.ReactNode }) => {
const [store] = useState(() => createStore());
return <Provider store={store}>{children}</Provider>;
};
export default StoreProvider;
Then in client
components, you can access the atoms using useAtom
and useAtomValue
, and get the current atom store using useStore
.
To access the value of the count atom in the store you would use:
const countValue = useAtomValue(countAtom, {
store: useStore(),
});
Note that if you leave off the useStore
, your code will be using the global atom value which you shouldn't use with the App Router.
As one last hint, watch out for how to safely initialize the reviews atom on route changes between detail pages. Remember, the Jotai store is global to the layout and contains the reviews as well as the cart.