1

我正在研究如何在我的应用程序中使用 RecoilJS,我喜欢 atomFamily 的概念——这似乎是跟踪列表中各个项目同时保持应用程序性能的好方法,因为每个项目的更新不会强制刷新整个列表。

我想以异步方式从远程服务器加载一组数据,比如说待办事项列表的项目(给出一个规范的例子),然后初始化 atomFamily 并从这些项目中的每一个创建一个反应组件。

我的第一个想法是创建一个 useEffect 挂钩。在其中我会获取数据,然后运行一个 for 循环并调用 atomFamily 为每个项目创建原子。

但后来我开始阅读有关 selectorFamily 的内容——听起来这可能是正确的方法?此外,有些原子效果(不稳定)看起来可能是执行此操作的正确方法,而不是使用普通的 useEffect 挂钩?现在我对在这里进行的正确方法感到困惑,并且我在互联网上没有找到很多关于此的信息。

你能指点我正确的方向吗?加载数据然后将其拉入 Recoil 系统的适当方法是什么?AtomFamily,选择器Family?我什至在正确的轨道上吗?

在此先感谢您的帮助,

格雷格

4

1 回答 1

2

我在Recoil Github 页面上发布了这个问题,并得到了几个高质量的答案。非常感谢 BenjaBobs 和 drarmstr 的帮助:

BenjaBobs 写道:

你有几个选择:

获取项目数组并存储在原子中,并使用 selectorFamily 访问该原子中的各个项目。如果您需要在某处显示列表,这可能是一个不错的选择,因为您现在有一个数组版本可以迭代

获取数组并遍历它们并将每个放入它自己的 atomFamily 成员中。

一次只获取一个,使用 selectorFamily。

将第一个和第三个选项结合起来,获取一个 id 列表并将它们放入一个 atom 中,然后使用 selectorFamily 懒惰地获取。

编辑:这是我的爱好项目中的一个状态,它使用我提到的第四种方法 https://github.com/BenjaBobs/HotsTools/blob/master/src/api/state/heroes.ts#L5-L129

Drarmstr 注释:

使用 selectorFamily() 适用于只读查询。使用 atomFamily() 可以允许您加载初始值,但随后允许本地突变。使用原子效果可以让您双向同步可变数据。

另请注意基于您选择加载数据的方式的一些后果。如果您使用 useEffect() 或某些异步机制将初始值加载到 atomFamily() 中:那么如果在加载数据之前读取原子,它们将使用默认原子值。如果你使用 selectorFamily() 来获取它们,使用 atomFamily() 和 selectorFamily() 作为默认值来获取初始值,或者通过原子效果中的 Promise 初始化值,那么反冲状态可以是“待定”在加载初始值时。这可以通过 React Suspense 自动管理或使用 Loadables 显式管理。

我跟进了以下问题:

@drarmstr - 假设我想使用具有默认 Promise 的 atom() 来获取我的项目列表。接下来,我想遍历列表项并创建单个原子——这就是练习的重点。所有这些都应该在同一个 Promise 中完成吗?

dramstr 回复:

如果您使用具有 Promise 默认值的 atom() 模式以允许本地可变状态和远程查询的默认值,那么处理实际项目状态本身的等价物就是使用 atomFamily()并提供一个默认的 selectorFamily() ,它使用 Promise 来查询单个项目的默认值。例如:

 const itemsState = atom({
    key: 'Items',
    default: fetch(items...),
 });
 
 const itemState = atomFamiliy({   key: 'Item',   default:
 selectorFamily({
     key: 'Item/Default',
     get: id => () => fetch(id...),   
    }),
 });

非常感谢那些做出回应的人,这对我了解 Recoil 的旅程很有帮助。

于 2021-02-14T05:11:42.897 回答