atomWithRefreshAndDefault
这是 atomWithDefault 的另一种实现方式
回顾 atomWithDefault 的行为
Section titled “回顾 atomWithDefault 的行为”如 atomWithDefault 章节的示例代码所示,当更新由其创建的原子后,两个原子之间的关联会断开,例如 count2Atom = atomWithDefault((get) => get(count1Atom) * 2)。
我们来确认一下具体发生了什么:
-
- 点击 “increment count1”,count1 变为 2,count2 变为 4
-
- 点击 “increment count2”,count1 仍为 2,count2 变为 5(关联已断开!)
更新 count2Atom 后,这两个原子不再有关联。因此:
- 点击 “increment count1” 只会递增 count1
- 即使重置 count2Atom,这种依赖关系也不会恢复
在某些场景下:
- 断开关联并重置后,它们应该恢复原有的关系
- 当原始原子更新时,派生原子应基于此被重置
- 我们想重置所有派生原子,但操作要尽可能简单
如何实现这些场景? 以下是一种声明式方式,创建一个可刷新的原子函数来替代 atomWithDefault。
const refreshCountAtom = atom(0)
const baseDataAtom = atom(1) // 原始数据,例如基础的 count1Atomconst dataAtom = atom( (get) => { get(refreshCountAtom) // 这在 atomWithRefresh 中有介绍 return get(baseDataAtom) }, (get, set, update) => { set(baseDataAtom, update) },)
const atomWithRefreshAndDefault = (refreshAtom, getDefault) => { const overwrittenAtom = atom(null) return atom( (get) => { const lastState = get(overwrittenAtom) if (lastState && lastState.refresh === get(refreshAtom)) { return lastState.value } return getDefault(get) }, (get, set, update) => { set(overwrittenAtom, { refresh: get(refreshAtom), value: update }) }, )}
// 这是 `atomWithDefault((get) => get(count1Atom) * 2)` 的替代方案const refreshableAtom = atomWithRefreshAndDefault( refreshCountAtom, (get) => get(dataAtom) * 2,)
// 只需更新一个原子即可重置const resetRootAtom = atom(null, (get, set) => { set(refreshCountAtom, get(refreshCountAtom) + 1)})