我应该构建一个本地数据层/应用程序状态来维护 React Native/Firestore 应用程序中的状态吗?

IT技术 reactjs react-native google-cloud-firestore expo react-native-firebase
2021-04-30 22:08:47

Firestore 的一个主要卖点是能够将其用作在线/离线事实来源。我现在正在以这种方式使用它:直接在操作上更新 Firestore 文档,然后监听 Firestore 数据库更改并将其映射回本地状态。然而,依靠这种延迟补偿和映射回本地状态不足以进行快速更新(即使是小文档大小的点击、切换)。例如,切换将“抖动”,因为 RN 切换假定在点击时移动,并且本地状态直到它已经返回时才会更新,请参见视频示例它在 Android 上看起来更糟,而且问题不仅限于基本的切换。

  1. 文档大小或查询结果大小对延迟补偿的影响更大吗?我们的文档大小现在非常小,最坏的情况是大约 1000 个查询结果集。我们可以将文档放大 1000 倍 (100kb) 并获得大小为 1 的查询结果集。更新:这里的测试似乎不一致,两种情况下的延迟补偿都不理想
  2. 以下哪些其他因素可能会影响延迟补偿?

    • 使用带有自定义索引的查询。注意:我们当前不是从缓存中读取,我们使用的是 JS SDK
    • 多次写入。对同一文档进行多次写入是否会使情况变得更糟(4 次快速写入与 2 次快速写入)。更新:不清楚这有很大的不同
    • 使用本机与 JS module。我们目前正在将 Firestore Web SDK 与 Expo 应用程序一起使用。更新:通过 React-Native Firestore 切换到原生module没有明显的性能提升
  3. 人们使用 React Native/Firestore 应用程序构建本地数据填充层/本地应用程序状态以帮助提高本地性能速度是否常见?是否有任何建议的图书馆?

在应用程序加载时,挂载侦听器,并将结果导出到要通过应用程序使用的上下文

const [user, setUser] = useState();

firebase.firestore().collection(`users/${user.uid}`).onSnapshot(qs => setUser(oldState => {
    const newState = {};
    qs.docChanges().forEach(change => {
      if (change.type === "added" || change.type === "modified") {
        newState[change.doc.id] = {
          docid: change.doc.id,
          ...change.doc.data(),
        };
      } else if (change.type === "removed") {
        delete oldState[change.doc.id];
      }
    });

    return {
      ...oldState,
      ...newState,
    };
  }))

切换通知的示例组件和函数:(开关抖动)

const toggleNotifications = (user, value) => {
  firebase.firestore().doc(`users/${user.uid}`).update({
    wantNotifications: value,
  });
};

const TestComponent = () => {
  //gets from context, set in listener mounted on app load
  const { user } = useUserContext();
  return (
    <Switch
      value={user.wantNotifications}
      onValueChange={value => toggleNotifications(user, value)}
    />
  );
};
2个回答

这不是答案,只是一个长评论:)

@learningAngular 例如,toggleNotifications只需要调用一个异步动作创建者,不用担心在react组件中放置任何逻辑。

相反,Redux 模式为做一些逻辑提供了空间,在这种情况下,因为用户的最后时刻决定是事实来源,因此调度函数将始终设置本地tempStateupdatingStatus在开始更新 firestore 之前,然后在 firestore Promise已解决或拒绝后将操作调度到 reducer重置updatingStatus然后选择器将检查是否updatingStatus为真的只依赖于本地,tempState否则依赖于监听的 Firestore 状态。最后,react组件使用选择器结果作为当前有效状态。

我没有回答这个问题,因为我没有那么多经验。我也很好奇是否有好的解决方案,但这就是我认为目前的解决方案。

我用特定的学习更新了答案,但经过大量测试,到目前为止我最大的一般学习是

  • 即使数据和环境相同,延迟补偿也可能非常不一致。正如其他问题中提到的那样,听众可能需要时间来“热身”。这里很难有一个标准的指标。
  • 文档大小确实会影响延迟补偿。到目前为止,其他一切都尚无定论。