将异步(通过网络)加载到 atomFamily/selectorFamily 反冲组件的正确方法是什么?
What's the appropriate way load async (over the network) into atomFamily/selectorFamily recoil component?
我正在研究如何在我的应用程序中使用 RecoilJS,我喜欢 atomFamily 的概念 - 这似乎是跟踪列表中的单个项目同时保持应用程序性能的好方法,因为每个项目的更新不会强制刷新整个列表。
我想以异步方式从远程服务器加载一组数据,比方说待办事项列表的项目(举一个典型的例子),然后初始化 atomFamily 并从每个项目创建一个反应组件项目。
我的第一个想法是创建一个 useEffect 挂钩。我会在其中获取数据,然后 运行 一个 for 循环并调用 atomFamily 为每个项目创建原子。
但后来我开始阅读有关 selectorFamily 的内容 - 听起来这可能是正确的方法?此外,有些原子效果(不稳定)看起来可能是执行此操作的正确方法,而不是使用普通的 useEffect 挂钩?现在我对在这里进行的正确方法感到困惑,而且我还没有在互联网上找到很多关于这个的信息。
你能给我指明正确的方向吗?加载数据然后将其拉入 Recoil 系统的合适方法是什么?原子家族、选择器家族?我在这里走对了吗?
在此先感谢您的帮助,
格雷格
我在 Recoil Github page 上发布了这个问题,并得到了几个高质量的答案。非常感谢 BenjaBobs 和 drarmstr 的帮助:
BenjaBobs 写道:
You have a couple of options:
fetch the array of items and store in an atom, and use a
selectorFamily to access individual items in that atom. If you need to
display the list somewhere, this can be a good choice since you now
have an array version to iterate over
fetch the array and iterate over them and put each into it's own
atomFamily member.
fetch only one at the time, using a selectorFamily.
Do a combination of the first and third options and fetch a list of
ids and put them into an atom and then use a selectorFamily to fetch
lazily.
EDIT: Here's a piece of state in my hobby project that uses the fourth
method I mentioned
https://github.com/BenjaBobs/HotsTools/blob/master/src/api/state/heroes.ts#L5-L129
Drarmstr 注释:
Using a selectorFamily() works for read-only queries. Using an
atomFamily() can allow you to load initial values, but then allow
local mutation. Using atom effects can allow you to bi-directionally
sync mutable data.
Also note some ramifications based on how you choose to load your
data. If you use useEffect(), or some async mechanism, to load initial
values into an atomFamily(): then if the atoms are read prior to the
data being loaded they will use the default atom value. If you use a
selectorFamily() to fetch them, use an atomFamily() with a
selectorFamily() as the default to fetch initial values, or initialize
the value via a Promise in an atom effect, then the recoil state can
be "pending" while you load the initial values. This can be managed
automatically via React Suspense or managed explicitly by using
Loadables.
我跟进了以下问题:
@drarmstr - let's assume I want to use an atom() with a default
Promise to fetch my list of items. Next, I'd want to iterate over the
list items and create individual atoms - the whole point of the
exercise. Should that all be done inside the same Promise?
dramstr 回复:
If you're using the pattern of an atom() with a Promise default to
allow for locally mutable state with a default from a remote query,
then the equivalent for dealing with the actual item state themselves
would be to use an atomFamily() for the items and provide a default
that is a selectorFamily() that uses a Promise to query the default
for the individual item. e.g.:
const itemsState = atom({
key: 'Items',
default: fetch(items...),
});
const itemState = atomFamiliy({ key: 'Item', default:
selectorFamily({
key: 'Item/Default',
get: id => () => fetch(id...),
}),
});
非常感谢那些回复的人,这对我理解 Recoil 的旅程很有帮助。
我正在研究如何在我的应用程序中使用 RecoilJS,我喜欢 atomFamily 的概念 - 这似乎是跟踪列表中的单个项目同时保持应用程序性能的好方法,因为每个项目的更新不会强制刷新整个列表。
我想以异步方式从远程服务器加载一组数据,比方说待办事项列表的项目(举一个典型的例子),然后初始化 atomFamily 并从每个项目创建一个反应组件项目。
我的第一个想法是创建一个 useEffect 挂钩。我会在其中获取数据,然后 运行 一个 for 循环并调用 atomFamily 为每个项目创建原子。
但后来我开始阅读有关 selectorFamily 的内容 - 听起来这可能是正确的方法?此外,有些原子效果(不稳定)看起来可能是执行此操作的正确方法,而不是使用普通的 useEffect 挂钩?现在我对在这里进行的正确方法感到困惑,而且我还没有在互联网上找到很多关于这个的信息。
你能给我指明正确的方向吗?加载数据然后将其拉入 Recoil 系统的合适方法是什么?原子家族、选择器家族?我在这里走对了吗?
在此先感谢您的帮助,
格雷格
我在 Recoil Github page 上发布了这个问题,并得到了几个高质量的答案。非常感谢 BenjaBobs 和 drarmstr 的帮助:
BenjaBobs 写道:
You have a couple of options:
fetch the array of items and store in an atom, and use a selectorFamily to access individual items in that atom. If you need to display the list somewhere, this can be a good choice since you now have an array version to iterate over
fetch the array and iterate over them and put each into it's own atomFamily member.
fetch only one at the time, using a selectorFamily.
Do a combination of the first and third options and fetch a list of ids and put them into an atom and then use a selectorFamily to fetch lazily.
EDIT: Here's a piece of state in my hobby project that uses the fourth method I mentioned https://github.com/BenjaBobs/HotsTools/blob/master/src/api/state/heroes.ts#L5-L129
Drarmstr 注释:
Using a selectorFamily() works for read-only queries. Using an atomFamily() can allow you to load initial values, but then allow local mutation. Using atom effects can allow you to bi-directionally sync mutable data.
Also note some ramifications based on how you choose to load your data. If you use useEffect(), or some async mechanism, to load initial values into an atomFamily(): then if the atoms are read prior to the data being loaded they will use the default atom value. If you use a selectorFamily() to fetch them, use an atomFamily() with a selectorFamily() as the default to fetch initial values, or initialize the value via a Promise in an atom effect, then the recoil state can be "pending" while you load the initial values. This can be managed automatically via React Suspense or managed explicitly by using Loadables.
我跟进了以下问题:
@drarmstr - let's assume I want to use an atom() with a default Promise to fetch my list of items. Next, I'd want to iterate over the list items and create individual atoms - the whole point of the exercise. Should that all be done inside the same Promise?
dramstr 回复:
If you're using the pattern of an atom() with a Promise default to allow for locally mutable state with a default from a remote query, then the equivalent for dealing with the actual item state themselves would be to use an atomFamily() for the items and provide a default that is a selectorFamily() that uses a Promise to query the default for the individual item. e.g.:
const itemsState = atom({
key: 'Items',
default: fetch(items...),
});
const itemState = atomFamiliy({ key: 'Item', default:
selectorFamily({
key: 'Item/Default',
get: id => () => fetch(id...),
}),
});
非常感谢那些回复的人,这对我理解 Recoil 的旅程很有帮助。