jotai guide学习

205 阅读1分钟

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
    } 
    // ... 
}