用于 React 的原始和灵活的状态管理
npm i jotai
Jotai 的发音是 “joe-tie”,在日语中意为 “状态”。
你可以在以下内容中尝试现场演示。演示 1 | 演示 2。
Jotai 与 Recoil 有什么不同?
- 极简的 API
- 没有字符串键
- 面向 TypeScript
首先创建一个原始的原子
一个原子代表一段状态。你只需要指定一个初始值,它可以是原始值,如字符串和数字,对象和数组。你可以创建任意多的原始原子。
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 })
在你的组件中使用原子
它可以像 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>
创建具有计算值的派生原子
通过传递一个 read 函数作为第一个参数,可以从现有的原子中创建一个新的只读原子。get 允许你获取任何原子的上下文值。
const doubledCountAtom = atom((get) => get(countAtom) * 2)
function DoubleCounter() {
const [doubledCount] = useAtom(doubledCountAtom)
return <h2>{doubledCount}</h2>
经验之谈
从多个原子创建一个原子
你可以结合多个原子来创建一个派生原子。
const count1 = atom(1)
const count2 = atom(2)
const count3 = atom(3)
const sum = atom((get) => get(count1) + get(count2) + get(count3))
或者如果你喜欢 fp 模式 …
const atoms = [count1, count2, count3, ...otherAtoms]
const sum = atom((get) => atoms.map(get).reduce((acc, count) => acc + count))
衍生的异步原子
你也可以把读函数变成一个异步函数。
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)
你可以创建一个可写的派生原子
在第二个参数中指定一个写函数。get 将返回一个原子的当前值。set 将更新一个原子的值。
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>
只写原子
就不要定义一个读函数。
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>
异步行动
只要把写函数变成一个异步函数,准备好后再调用 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")}>compute</button>
安装说明
这个包需要一些同行的依赖,你需要自己安装。