Jotai是一个状态管理库,采用受recoil启发的原子模型。
1. 创建atom
// 声明atom,支持多种类型
const countAtom = atom(1)
const objAtom = atom({
name: 'abc',
age: 18,
})
const arrAtom = atom([1, 2, 3])
// 使用atom
const [count, setCount] = useAtom(countAtom)
2. 持久化atom
// 1. 从jotai/utils工具包中导入atomWithStorage
import { atomWithStorage } from 'jotai/utils';
const themeAtom = atomWithStorage('dark', false)
// 使用
const [theme, setTheme] = useAtom(themeAtom)
// 2.简单替代
const strAtom = atom(localStorage.getItem('key') ?? 'abc')
const strAtomWithStorage = atom(
(get) => get(strAtom),
(get, set, newStr) => {
set(strAtom, newStr)
localStorage.setItem('key', newStr)
}
)
const [str, setStr] = useAtom(strAtomWithStorage)
// 3. 使用sessionStorage
import { atomWithStorage, createJSONStorage } from "jotai/utils";
const storage = createJSONStorage(() => sessionStorage);
const someAtom = atomWithStorage("some-key", someInitialValue, storage);
3. 派生原子
- 只写原子
- 只读原子
- 读写原子
const textAtom = atom('readonly');
const readOnlyAtom = atom((get) => get(textAtom).toUpperCase());
const writeOnlyAtom = atom(null, (get, set, update) => {
const nextValue =
typeof update === 'function' ? update(get(textAtom)) : update
set(textAtom, nextValue)
})
const readWriteAtom = atom(
(get) => get(textAtom).toUpperCase(),
(_, set, newText) => {
set(textAtom, newText)
}
)
4. 异步原子
- 异步读原子
// 结合suspense使用
const counter = atom(1)
const asyncAtom = atom(async (get) => get(counter) * 5)
//
<Suspense fallback={<div>Loading...</div>}>
<Async />
</Suspense>
// 使用loadable
const asyncAtom = atom(async (get) => get(counter) * 5)
const loadableAtom = loadable(asyncAtom)
const [value] = useAtom(loadableAtom)
if (value.state === 'hasError') return <div>Error</div>
if (value.state === 'loading') return <div>Loading...</div>
return <div>Async {value.data}</div>
- 异步写原子
// 异步写原子不会触发suspense
const asyncIncrementAtom = atom(null, async (get, set) => {
// await something
set(countAtom, get(countAtom) + 1);
});
// 可以通过这种模式,触发suspense
const request = async () => fetch('https://...').then((res) => res.json())
const baseAtom = atom(0)
const Component = () => {
const [value, setValue] = useAtom(baseAtom)
const handleClick = () => {
setValue(request()) // Will suspend until request resolve
}
// ...
}