访问 jotai.org 或运行 npm i jotai
Jotai 可以从简单的 useState 替代方案扩展到企业级 TypeScript 应用。
- 极简核心 API(2kb)
- 众多实用工具和扩展
- 无字符串键(相比 Recoil)
首先,创建一个原始 atom
atom 代表一个状态片段。你只需要指定一个初始值,可以是字符串和数字等原始值,也可以是对象和数组。你可以创建任意多个原始 atom。
import { atom } from 'jotai'
const countAtom = atom(0)
const countryAtom = atom('日本')
const citiesAtom = atom(['东京', '京都', '大阪'])
const mangaAtom = atom({ '龙珠': 1984, '海贼王': 1997, 火影忍者: 1999 })
在组件中使用 atom
它的用法类似于 React.useState
:
import { useAtom } from 'jotai'
function Counter() {
const [count, setCount] = useAtom(countAtom)
return (
<h1>
{count}
<button onClick={() => setCount((c) => c + 1)}>加一</button>
...
创建具有计算值的派生 atom
通过传递一个读取函数作为第一个参数,可以从现有的 atom 创建一个新的只读 atom。get
允许你获取任何 atom 的上下文值。
const doubledCountAtom = atom((get) => get(countAtom) * 2)
function DoubleCounter() {
const [doubledCount] = useAtom(doubledCountAtom)
return <h2>{doubledCount}</h2>
}
从多个 atom 创建一个 atom
你可以组合多个 atom 来创建一个派生 atom。
const count1 = atom(1)
const count2 = atom(2)
const count3 = atom(3)
const sum = atom((get) => get(count1) + get(count2) + get(count3))
或者如果你喜欢函数式编程模式...
const atoms = [count1, count2, count3, ...otherAtoms]
const sum = atom((get) => atoms.map(get).reduce((acc, count) => acc + count))
派生异步 atom
你也可以将读取函数设为异步函数。
const urlAtom = atom('https://json.host.com')
const fetchUrlAtom = atom(async (get) => {
const response = await fetch(get(urlAtom))
return await response.json()
})
function Status() {
// 在 urlAtom 更改并且上面的异步函数完成后重新渲染组件
const [json] = useAtom(fetchUrlAtom)
...
你可以创建一个可写的派生 atom
在第二个参数中指定一个写入函数。get
将返回 atom 的当前值。set
将更新 atom 的值。
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}>减少</button>
...
只写派生 atom
只需不定义读取函数。
const multiplyCountAtom = atom(null, (get, set, by) =>
set(countAtom, get(countAtom) * by),
)
function Controls() {
const [, multiply] = useAtom(multiplyCountAtom)
return <button onClick={() => multiply(3)}>三倍</button>
}
异步操作
只需将写入函数设为异步函数,并在准备好时调用 set
。
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')}>计算</button>
...