JotaiJotai

状態
Primitive and flexible state management for React

Comparison

Jotai was born to solve extra re-render issues in React. An extra re-render is when the render process produces the same UI result, where users won't see any differences.

To tackle this issue with React context (useContext + useState), one would require many contexts and face some issues.

  • Provider hell: It's likely that your root component has many context providers, which is technically okay, and sometimes desirable to provide context in different subtree.
  • Dynamic addition/deletion: Adding a new context at runtime is not very nice, because you need to add a new provider and its children will be re-mounted.

Traditionally, a top-down solution to this is to use a selector interface. The use-context-selector library is one example. The issue with this approach is the selector function needs to return referentially equal values to prevent re-renders, and this often requires a memoization technique.

Jotai takes a bottom-up approach with the atomic model, inspired by Recoil. One can build state combining atoms, and optimize renders based on atom dependency. This avoids the need for memoization.

Jotai has two principles.

  • Primitive: Its basic interface is simple, like useState.
  • Flexible: Derived atoms can combine other atoms and enable useReducer style with side effects.

How is Jotai different from useContext of React?

Jotai's core API is minimalistic and makes it easy to build utilities based upon it.

Analogy

You can view Jotai as a drop-in replacement to useContext, as it actually uses it in the core. Except Jotai is aiming for simplicity, minimalistic API and can do much more than useContext & useState.

Usage difference

We can see how we used to share data to children, compared to how we do it with Jotai. But let's use a real-world example where we have multiple Context in our app.

// 1. useState local state
const Component = () => {
const [state, setState] = useState(0)
}
// 2. Lift local state up and share it via context
const StateContext = createContext()
const Parent = ({ children }) => {
return (
<StateContext.Provider value={useState(0)}>
{children}
</StateContext.Provider>
)
}
const Component = () => {
const [state, setState] = useContext(StateContext)
}
// 3. Have multiple states and contexts
const State1Context = createContext()
const State2Context = createContext()
const Parent = ({ children }) => (
<State1Context.Provider value={useState(0)}>
<State2Context.Provider value={useState(0)}>
{children}
</State2Context.Provider>
</State1Context.Provider>
)
const Component1 = () => {
const [state, setState] = useContext(State1Context)
}
const Component2 = () => {
const [state, setState] = useContext(State2Context)
}

Now let's see how Jotai simplify it for us. You can just use atoms instead of multiple Context.

import { Provider, atom, useAtom } from 'jotai'
const atom1 = atom(0)
const atom2 = atom(0)
// Optional: you can use Provider's just like useContext,
// ...but if you only need one,
// ...you can just omit it and Jotai will use a default one (called Provider-less mode).
const Parent = ({ children }) => {
return <Provider>{children}</Provider>
}
const Component1 = () => {
const [state, setState] = useAtom(atom1)
}
const Component2 = () => {
const [state, setState] = useAtom(atom2)
}

How is Jotai different from Zustand?

Name

Jotai means "state" in Japanese. Zustand means "state" in German.

Analogy

Jotai is like Recoil. Zustand is like Redux.

Where state resides

Jotai state is within React component tree. Zustand state is in the store outside React.

How to structure state

Jotai state consists of atoms (i.e. bottom-up). Zustand state is one object (i.e. top-down).

Technical difference

The major difference is the state model. Zustand is a single store (although you could create multiple separate stores), while Jotai consists of primitive atoms and allows composing them together. In this sense, it's the matter of programming mental model.

Jotai can be a replacement for useState+useContext. Instead of creating multiple contexts, atoms share one big context.

Zustand is an external store and the hook is to connect the external world to the React world.

When to use which

  • If you need a replacement for useState+useContext, Jotai fits well.
  • If you want to update state outside React, Zustand works better.
  • If code splitting is important, Jotai should perform well.
  • If you prefer Redux devtools, Zustand is good to go.
  • If you want to make use of Suspense, Jotai is the one.

How is Jotai different from Recoil?

(Disclaimer: the author is not very familiar with Recoil, this may be biased and inaccurate.)

Developer

  • Jotai is developed with collective work by a few developers in Poimandres (formerly react-spring) org.
  • Recoil is developed by a team at Facebook.

Basis

  • Jotai is focusing on primitive APIs for easy learning, and it's unopinionated. (The same philosophy with Zustand)
  • Recoil is full featured for big apps with complex requirements.

Technical difference

  • Jotai depends on atom object referential identities.
  • Recoil depends on atom string keys.

When to use which

  • If you want to learn something new, either should work.
  • If you like Zustand, Jotai would also be pleasant.
  • If your app heavily requires state serialization (storing state in storage, server, or URL), Recoil comes with good features.
  • If you need React Context alternatives, Jotai comes with enough features.
  • If you would try to create a new library, Jotai might give good primitives.
  • Otherwise, both are pretty similar about the general goals and basic techniques, so please try both and share your feedback with us.