JotaiJotai

Jotai
React 原始而灵活的状态管理

Async

所有的原子都支持异步行为,如异步读取或异步写入。然而,这里描述的API可以提供更多的控制。

loadable

如果你不希望异步原子挂起或抛出到错误边界(例如,为了更细粒度的加载和错误逻辑控制),你可以使用 loadable 工具。

它对任何原子都能起作用。只需用 loadable 工具包装你的原子。它返回一个具有三种状态之一的值:loadinghasDatahasError

{
state: 'loading' | 'hasData' | 'hasError',
data?: any,
error?: any,
}
import { loadable } from "jotai/utils"
const asyncAtom = atom(async (get) => ...)
const loadableAtom = loadable(asyncAtom)
// 不需要被 <Suspense> 元素包裹
const Component = () => {
const [value] = useAtom(loadableAtom)
if (value.state === 'hasError') return <Text>{value.error}</Text>
if (value.state === 'loading') {
return <Text>Loading...</Text>
}
console.log(value.data) // Promise的结果
return <Text>Value: {value.data}</Text>
}

atomWithObservable

参考:https://github.com/pmndrs/jotai/pull/341

使用方法

import { useAtom } from 'jotai'
import { atomWithObservable } from 'jotai/utils'
import { interval } from 'rxjs'
import { map } from 'rxjs/operators'
const counterSubject = interval(1000).pipe(map((i) => `#${i}`))
const counterAtom = atomWithObservable(() => counterSubject)
const Counter = () => {
const [counter] = useAtom(counterAtom)
return <div>count: {counter}</div>
}

atomWithObservable 函数从 rxjs(或类似)的 subjectobservable 创建一个原子。 其值将是流中最后发出的值。

要使用这个原子,你需要用 <Suspense> 包裹你的组件。查看 guides/async

初始值

atomWithObservable 接受第二个可选参数 { initialValue },该参数允许为原子指定初始值。如果提供了 initialValue,那么 atomWithObservable 将不会挂起,并且在从 observable 接收到第一个值之前显示初始值。initialValue 可以是一个值,也可以是一个返回值的函数

const counterAtom = atomWithObservable(() => counterSubject, {
initialValue: 10,
})
const counterAtom2 = atomWithObservable(() => counterSubject, {
initialValue: () => Math.random(),
})

Codesandbox

unwrap

unwrap 工具将把一个异步原子转换为一个同步原子,就像 loadable 一样。 与 loadable 不同,可以配置回退值。 与 loadable 不同,错误不会被处理,而是直接抛出。

unwrap 的使用场景是为了简化派生原子。 这对于 v2 API 特别有用, 因为在读取函数中的 get 不解析 promise。

签名

function unwrap<Value, Args extends unknown[], Result>(
anAtom: WritableAtom<Value, Args, Result>,
): WritableAtom<Awaited<Value> | undefined, Args, Result>
function unwrap<Value, Args extends unknown[], Result, PendingValue>(
anAtom: WritableAtom<Value, Args, Result>,
fallback: (prev?: Awaited<Value>) => PendingValue,
): WritableAtom<Awaited<Value> | PendingValue, Args, Result>
function unwrap<Value>(anAtom: Atom<Value>): Atom<Awaited<Value> | undefined>
function unwrap<Value, PendingValue>(
anAtom: Atom<Value>,
fallback: (prev?: Awaited<Value>) => PendingValue,
): Atom<Awaited<Value> | PendingValue>

使用方法

import { atom } from 'jotai'
import { unwrap } from 'jotai/utils'
const countAtom = atom(0)
const delayedCountAtom = atom(async (get) => {
await new Promise((r) => setTimeout(r, 500))
return get(countAtom)
})
const unwrapped1Atom = unwrap(delayedCountAtom)
// 当挂起时,值为 `undefined`
const unwrapped2Atom = unwrap(delayedCountAtom, (prev) => prev ?? 0)
// 初始值为 `0`,后续更新保持前一个值。