在Redux中使用离线Firestore的最佳方法是什么?

时间:2018-10-04 09:34:10

标签: reactjs react-redux google-cloud-firestore offline create-react-app

tl; dr 是在尝试更新后端数据库(例如Firestore)之前更新redux存储的一种好习惯,还是那里有另一种“最佳实践”解决方案?

目前,我已经使用create react app创建了一个应用。后端数据存储在Firestore中。应用加载时,最初,它会从Firestore获取一系列项目,并将其加载到UI用于呈现内容的Redux存储中。

一切都很好。

我的问题是关于离线时如何实施CRUD操作(例如创建项目)。出于记录,CRA正在缓存应用程序,因此UI可以脱机工作(如果商店中有数据),所以我的问题不是,这是关于最好将数据发送到Firebase并分派(相同)有效负载的顺序到redux商店。

请注意,下面的“ db”是一个与Firestore连接的数据库(在其他位置配置),当我谈论脱机使用Firestore时,我所谈论的是enablePersistence,这是iOS和Android的默认设置。而且我正在使用Thunk。

例如,我看到一个常见的Redux动作创建者模式,如下所示。在这种情况下,我将使用它来创建一个新项目:

export const createProject = projectData => async dispatch => {
  dispatch({ type: CREATE_PROJECT_START });
  try {
    await db
      .collection("projects")
      .doc(projectData.project_uid)
      .set({ ...projectData });
    dispatch({ type: CREATE_PROJECT_SUCCESS, payload: projectData });
  } catch (e) {
    dispatch({ type: CREATE_PROJECT_FAIL, payload: e.message });
  }
};

行为是这样的,直到将承诺从Firebase返回之前,才不会将有效负载分配给Redux。

在测试时,我可以关闭网络并创建一个新项目。调用createProject函数(通过表单提交)时,控制台会亮起net :: ERR_INTERNET_DISCONNECTED消息,这是预期的行为。

但是,当用户从表单返回到呈现所有项目的页面时,由于Firebase承诺尚未完成,因此不会呈现新项目。

但是,很棒的是,当我重新启动网络时(我只测试了几分钟,并且不确定经过很长一段时间后它的工作情况如何),Firebase将会继续它在线,发送数据,返回承诺,然后可以将其分发到Redux的事实。

虽然很棒,但这并不是最佳的用户体验,因此我实现了如下所示的小调整:

export const createProject = projectData => async dispatch => {
  dispatch({ type: CREATE_PROJECT_START });
  try {
    dispatch({ type: CREATE_PROJECT_SUCCESS, payload: projectData });
    await db
      .collection("projects")
      .doc(projectData.project_uid)
      .set({ ...projectData });
  } catch (e) {
    dispatch({ type: CREATE_PROJECT_FAIL, payload: e.message });
  }
};

只需在调用db上的set方法之前,将分派移到Redux上,就可以做到这一点,因为项目在UI中创建后立即呈现给用户。实际上,即使数据库处于脱机状态,用户也可以执行几项更改,这些更改都可以正确反映在UI中。

错误仍然在控制台中消失,再次出现。并且当网络连接重新建立后,Firestore确实会在后台接收数据。

那么,话虽这么说,在数据库更新之前将分派到Redux是一种好/不好的做法,和/或有没有更好的方法呢?

1 个答案:

答案 0 :(得分:1)

我本人最近遇到了这个问题,起初做错了事,所以虽然痛苦/教训仍然很新鲜。

Firestore使用的同步模型是Promise的解决方案,旨在为开发人员提供处理拒绝失败的机会。无论是立即发布,还是将来某个时候重新发布该应用,例如使开发人员有机会重试或回滚更改。

有效使用此错误处理机制会导致建立状态模型,从而使应用程序的本地状态必须主导中心状态。

回答有关Redux最佳实践的问题。只要其减速器保持“纯”,相对于局部状态操纵发生外部副作用的时间就无关紧要。

许多Redux异步中间件解决方案都相对于Reducer运行在不同的点,例如Thunk和Sagas之前,Epic之后,然后循环。我觉得这有点奇怪,因为这不是我们惯用的。不过从本质上讲,什么时候发生对开发人员而言,对于手边的用例而言,最有意义的是什么。

我猜这个问题的作者不久前就破解了。但是,一旦了解了Firestore的同步模型,仍然存在如何最好地处理拒绝问题,使用大量排队的Promises脱机执行性能,处理由于Pro App重新启动而没有Promises时失败的后端写入等问题。

会对经验和实现这些东西的指针非常感兴趣:-)