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.