使用 Recoil 创建和读取数千个项目的状态

Create and Read State for thousands of items using Recoil

我刚开始在一个新项目中使用 Recoil,我不确定是否有更好的方法来完成这个。

我的应用程序是一个基本编辑包含对象数组的 JSON 文件的界面。它读入文件,根据特定 属性 将对象分组到选项卡中,然后用户可以导航选项卡,查看每个选项卡的几百个值,进行更改,然后保存更改。

我正在使用反冲,因为它允许我从我的应用程序中的任何位置访问每个输入的状态,这使得保存更容易 - 理论上...

为了为 JSON 文件中的每个对象生成状态,我创建了一个 returns null 的组件,然后映射到初始数组,创建组件,它使用 AtomFamily 创建 Recoil 状态,然后还将 ID 保存到另一个 Recoil 状态,这样我就可以保留所有内容的列表。

问题 1这些是更好的方法吗? null 组件感觉不对,但是将整个数组存储在单个状态中会导致在每次按键时重新呈现 everything

为了保存数据,我有一个调用函数的按钮。该函数只需要获取 ID,遍历它们,获取每个 ID 的状态,然后将它们推入数组。我也使用 Selector 完成了此操作,但问题是由于 Hooks 规则,我无法从函数调用 getRecoilValue - 但如果我将值提供给父组件,它会再次减慢一切。

问题 2 我很确定我错过了考虑存储状态和使用挂钩的正确方法,但我还没有找到任何用于此特定用途的示例case - 需要预先生成状态,然后在保存时再次访问它。有什么指导吗?

问题 1

习惯空渲染组件,你几乎无法通过 Recoil 避免它们,更一般地说,这个 hooks-first React 世界

关于函数内的 useRecoilValue:你是对的,你应该利用 useRecoilCallback 来完成这类任务。使用 useRecoilCallback 你有一个中心点,你可以在这里立即获取和设置你想要的任何东西。看看这个 working CodeSandbox 我试图复制(最简单的方式)你的用例。 SaveData 组件(不需要专用组件,您可以只公开 Recoil 回调而无需创建临时组件)如下

const SaveData = () => {
  const saveData = useRecoilCallback(({ snapshot }) => async () => {
    const ids = await snapshot.getPromise(carIds);
    for (const carId of ids) {
      const car = await snapshot.getPromise(cars(carId));
      const carIndex = db.findIndex(({ id }) => id === carId);
      db[carIndex] = car;
    }
    console.log("Data saved, new `db` is");
    console.log(JSON.stringify(db, null, 2));
  });

  return <button onClick={saveData}>Save data</button>;
};

如你所见:

  • 通过const ids = await snapshot.getPromise(carIds);

    检索所有id
  • 它使用 id 从原子家族 const car = await snapshot.getPromise(cars(carId));

    中检索所有汽车

所有这些都在一个中心点,没有钩子,也没有订阅原子更新的组件。

问题 2

您的用例有几种方法:

  • 在应用程序启动时创建空原子,更新它们,最后保存它们。这就是 my CodeSandbox does

  • 做同样的事情但是通过RecoilRoot' initialState prop

    初始化原子
  • Recoil 正在更新每个原子的变化。 useRecoilTransactionObserver 可以做到这一点,但请注意,它目前被标记为不稳定。很快就会有一种新的方法来做同样的事情(我猜),但目前这是唯一的解决方案

后者是“更聪明”的方法,但它实际上取决于您的用例,是否真的想在每个原子更新时更新 JSON 取决于您自己

希望对您有所帮助,如果我遗漏了什么请告诉我