title | description | nav |
---|---|---|
Introduction |
How to use Jotai |
0 |
npm install jotai
or yarn add jotai
Jotai is pronounced "joe-tie" and means "state" in Japanese.
You can try live demos here: Demo 1 | Demo 2.
- Minimalistic API
- No string keys
- TypeScript oriented
An atom represents a piece of state. All you need is to specify an initial value, which can be a primitive value like a string, number, object or array. You can create as many primitive atoms as you like.
import { atom } from 'jotai'
const countAtom = atom(0)
const countryAtom = atom('Japan')
const citiesAtom = atom(['Tokyo', 'Kyoto', 'Osaka'])
const mangaAtom = atom({ 'Dragon Ball': 1984, 'One Piece': 1997, Naruto: 1999 })
Use an atom like you'd use React.useState
:
import { useAtom } from 'jotai'
function Counter() {
const [count, setCount] = useAtom(countAtom)
return (
<h1>
{count}
<button onClick={() => setCount(c => c + 1)}>one up</button>
A new read-only atom can be created from existing atoms by passing a read
function as the first argument. get
allows you to fetch the contextual value
of any atom.
const doubledCountAtom = atom((get) => get(countAtom) * 2)
function DoubleCounter() {
const [doubledCount] = useAtom(doubledCountAtom)
return <h2>{doubledCount}</h2>
You can combine atoms to create a derived atom.
const count1Atom = atom(1)
const count2Atom = atom(2)
const count3Atom = atom(3)
const sum = atom((get) => get(count1Atom) + get(count2Atom) + get(count3Atom))
Or if you like fp patterns ...
const atoms = [count1Atom, count2Atom, count3Atom, ...otherAtoms]
const sum = atom((get) => atoms.map(get).reduce((acc, count) => acc + count))
You can make the read function an async function.
const urlAtom = atom("https://json.host.com")
const fetchUrlAtom = atom(
async (get) => {
const response = await fetch(get(urlAtom))
return await response.json()
}
)
function Status() {
// Re-renders the component after urlAtom changed and the async function above concludes
const [json] = useAtom(fetchUrlAtom)
Specify a write function at the second argument. get
will return the current
value of an atom. set
will update an atom's value.
const decrementCountAtom = atom(
(get) => get(countAtom),
(get, set, _arg) => set(countAtom, get(countAtom) - 1),
)
function Counter() {
const [count, decrement] = useAtom(decrementCountAtom)
return (
<h1>
{count}
<button onClick={decrement}>Decrease</button>
To make a write-only atom, don't define a read function by passing null
as the
first argument.
const multiplyCountAtom = atom(null, (get, set, by) => set(countAtom, get(countAtom) * by))
function Controls() {
const [, multiply] = useAtom(multiplyCountAtom)
return <button onClick={() => multiply(3)}>triple</button>
Make the write function an async function, and call set
when you're ready.
const fetchCountAtom = atom(
(get) => get(countAtom),
async (_get, set, url) => {
const response = await fetch(url)
set(countAtom, (await response.json()).count)
}
)
function Controls() {
const [count, compute] = useAtom(fetchCountAtom)
return <button onClick={() => compute("http://count.host.com")}>compute</button>