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

Posted

技术标签:

【中文标题】我应该构建本地数据层/应用程序状态来维护 React Native/Firestore 应用程序中的状态吗?【英文标题】:Should I build a local data layer/app state to maintain state in a React Native/Firestore App? 【发布时间】:2020-07-29 22:09:38 【问题描述】:

Firestore 的一个主要卖点是能够将其用作在线/离线事实来源。我现在以这种方式使用它:直接在操作上更新 Firestore 文档,然后侦听 Firestore DB 更改并将其映射回本地状态。但是,依靠这个latency compensation 并映射回本地状态不足以进行快速更新(即使文档很小也可以点击、切换)。例如,当 RN 切换假定在点击时切换时,切换将“抖动”,并且本地状态在它已经返回 see video example 之前尚未更新。在 android 上看起来更糟,而且问题不仅限于基本切换。

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

    以下哪些其他因素可能会影响延迟补偿?

    使用带有自定义索引的查询。注意:我们目前没有从缓存中读取,我们使用的是 JS SDK 多次写入。对同一文档的多次写入是否会使情况变得更糟(4 次快速写入与 2 次快速写入)。 更新:不清楚这是否有很大的不同。 使用本机与 JS 模块。我们目前正在将 Firestore Web SDK 与 Expo 应用程序一起使用。 更新:通过 React-Native Firestore 切换到原生模块并没有明显的性能提升

    人们使用 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)
    />
  );
;

【问题讨论】:

我建议使用react-redux-firebase 来处理与firebase 和firestore 的异步通信。 @Makan 谢谢!侦听器的自动绑定/解除绑定以及将集合映射到本地状态很好,但不确定它是否直接回答了这个问题。我认为它 react-redux-firebase 提供的状态仍然依赖于更新 firestore 数据库来接收更新。我的理解错了吗? 你是对的 react-redux-firestore 也从 firestore 接收更新,但我想说的是利用 redux 提供的模式来保持状态几乎同步更新。在此模式中,更新 firestore 将通过最终更新状态的异步调度操作。但是,它让我们有机会在调度操作之前更新本地状态,因此 React 组件可以依赖始终与 Firestore 同步的本地状态。 【参考方案1】:

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

@learningAngular 例如,在toggleNotifications 中只需要调用一个async action creator 并且不用担心将任何逻辑放入react 组件中。

相反,Redux 模式为执行一些逻辑提供了空间,在这种情况下,因为用户的最后一刻决定是事实的来源,所以调度函数总是在开始更新 firestore 之前设置本地 tempStateupdatingStatus,然后在 firestore 承诺之后已解决或已拒绝将操作分派给减速器以重置 updatingStatus。然后selector 将检查updatingStatus 是否为真,仅依赖本地tempState,否则依赖监听的firestore 状态。最后,react 组件使用选择器结果作为当前有效状态。

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

【讨论】:

【参考方案2】:

我用具体的学习更新了答案,但经过大量测试,我迄今为止最大的一般学习是

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

【讨论】:

以上是关于我应该构建本地数据层/应用程序状态来维护 React Native/Firestore 应用程序中的状态吗?的主要内容,如果未能解决你的问题,请参考以下文章

业务层中的实例方法与静态方法[关闭]

领域驱动设计 - 层应该如何组织?

我应该或不应该如何一起使用 Cassandra 和 Redis 来构建可扩展的一对一聊天应用程序?

Maven构建多模块项目

数据访问层应该如何构建?

域、DAO 和服务层