useRecoilCallback(callback, deps)
这个钩子类似于 useCallback()
,但它还将为你的回调提供与 Recoil 状态交互的 API。这个钩子可以用来构建一个回调函数,该回调函数可以访问 Recoil 状态的只读 Snapshot
,并能够异步更新当前 Recoil 状态。
使用这个钩子的一些动机可能包括
- 异步读取 Recoil 状态,而不会在原子或选择器更新时订阅 React 组件重新渲染。
- 将昂贵的查找推迟到一个异步操作中,你不想在渲染时进行。
- 执行你想要读取或写入 Recoil 状态的副作用。
- 动态更新原子或选择器,我们可能在渲染时不知道要更新哪个原子或选择器,所以我们不能使用
useSetRecoilState()
. - 预取 渲染前的數據。
type CallbackInterface = {
snapshot: Snapshot,
gotoSnapshot: Snapshot => void,
set: <T>(RecoilState<T>, (T => T) | T) => void,
reset: <T>(RecoilState<T>) => void,
refresh: <T>(RecoilValue<T>) => void,
transact_UNSTABLE: ((TransactionInterface) => void) => void,
};
function useRecoilCallback<Args, ReturnValue>(
callback: CallbackInterface => (...Args) => ReturnValue,
deps?: $ReadOnlyArray<mixed>,
): (...Args) => ReturnValue
callback
- 用户回调函数,带有一个提供回调接口的包装函数。更改状态的回调将被排队以异步更新当前 Recoil 状态。包装函数的类型签名与返回回调的类型签名匹配。deps
- 用于记忆回调的可选依赖项集合。与useCallback()
一样,生成的回调默认情况下不会被记忆,并且每次渲染都会产生一个新函数。你可以传递一个空数组来始终返回相同的函数实例。如果你在deps
数组中传递值,如果任何依赖项的引用相等性发生变化,就会使用一个新函数。这些值随后可以在你的回调函数体内使用,而不会变得陈旧。(参见useCallback
)你可以 更新 eslint 以帮助确保正确使用它。
回调接口
snapshot
-Snapshot
提供了访问快照时的 Recoil 原子状态的只读视图。虽然原子值是静态的,但异步选择器可能仍然会解析。快照将在同步或异步回调的持续时间内保留,但如果你将它存储并使用超出该范围,那么你需要 显式保留它.gotoSnapshot
- 将更新全局状态以匹配提供的Snapshot
排入队列。set
- 将原子或选择器的值设置为指定值排入队列。与其他地方一样,你可以直接提供新值,也可以提供一个返回新值的更新器函数,该函数将当前值作为参数。当前值表示当前事务中所有其他排队的状态更改。reset
- 将原子或选择器的值重置为其默认值。refresh
- 刷新选择器缓存。transact_UNSTABLE
- 执行事务。请参阅useRecoilTransaction_UNSTABLE()
文档.
注意:回调接口可能会延迟地按需计算属性,以避免开销。因此,你不应该使用扩展运算符将回调接口传递,而是应该显式地解引用属性或传递整个代理对象。
延迟读取示例
此示例使用 useRecoilCallback()
来延迟读取状态,而不会在状态更改时订阅组件重新渲染。
import {atom, useRecoilCallback} from 'recoil';
const itemsInCart = atom({
key: 'itemsInCart',
default: 0,
});
function CartInfoDebug() {
const logCartItems = useRecoilCallback(({snapshot}) => async () => {
const numItemsInCart = await snapshot.getPromise(itemsInCart);
console.log('Items in cart: ', numItemsInCart);
}, []);
return (
<div>
<button onClick={logCartItems}>Log Cart Items</button>
</div>
);
}