I’ve been stressing out several React global state libraries in the past months. Last week it was Jotai’s time.
I liked the concept of “atoms” and how they feel like autonomous useState
parts, and how they can be share state among components. I remember trying to write something like this in the past. Jotai seems to be what I tried to do back then:
import {atom} from 'jotai'; export const nameAtom = atom('hello');
Pretty much a global useState
here, which is great:
import {useAtom} from 'jotai'; import {nameAtom} from './state'; function App() { const [name, setName] = useAtom(nameAtom); //... }
In large, real-world applications you’d like to write mutation methods to implement specific logic, rather than having them scattered over the components. Thus we should not make setName
public; instead we should provide more specific methods.
In Jotai, while reading the state is trivial, I found writing mutations to be rather cumbersome. The syntax of “writing atoms” is, to my tired eyes, very convoluted:
export const setSurnameAtom = atom(null, (get, set, surname) => { set(nameAtom, get(nameAtom) + ' ' + surname); }); //... function App() { const [, setSurname] = useAtom(setSurnameAtom); }
After giving it some thought, it occurred me that since useAtom
is a hook, I can compose a custom hook over it. And then it all clicked:
export function useName() { const [name, setName] = useAtom(nameAtom); return useMemo(() => ({ value: name, setSurname(surname: string) { setName(name + ' ' + surname); }, }), [name, setName]); }
Usage of this custom hook is straightforward, crystal clear:
import {useName} from './state'; function App() { const name = useName(); return <> <h1>{name.value}</h1> <button onClick={() => name.setSurname('foo')}> Set surname </button> </>; }
This is a truly global custom useState
hook. This works amazingly well with VSCode autocomplete. This is easy to read. This is beautiful.
In the custom hook above, note the use of useMemo
. It cuts down a lot of the processing in inside the custom hook, and it was an insight I had after briefly talking to Daishi Kato himself, the author of Jotai, about this custom hook idea. The future useEvent
hook will optimize the button call a little further.
Jotai, unfortunately, has a huge drawback of not allowing accessing atoms outside a React component.