【问题标题】:React routing and persistence on page refresh在页面刷新时反应路由和持久性
【发布时间】:2015-04-14 09:57:58
【问题描述】:

我正在使用带有 react-router 和 Reflux 的 React 作为我的数据存储,但我不确定如何最好地处理持久性以允许页面刷新。

我的组件使用 Reflux.connect 连接到存储,但由于存储从后端获取数据,因此在组件首次初始化和渲染时它还不可用。

当用户从一开始就进入我的应用程序时,所有这些数据都会按顺序加载并在需要时可用,但如果进一步向下触发页面刷新,react 会尝试渲染依赖数据的组件那还没有。

我通过不断在 LocalStorage 中保存数据副本并从 Reflux 存储 getInitialState() 中提供数据来解决这个问题,以便所有组件在渲染之前获取数据。

我想知道这是否是正确的方法。当由于某种原因本地存储数据被清除或损坏时,界面变为空白,因为组件无法访问正确的数据。子结构和属性不存在并触发 javascript 错误。这似乎是一个混乱且不可靠的解决方案。

我很想知道用什么模式来解决这个问题。

----- 编辑 ----- 回答 WiredPrairie 的评论:

1) 为什么要用 getInitialState 中的数据初始化组件?

当我的组件使用 Reflux.connect 时,它们在第一次渲染时还没有处于其状态的数据,因为存储仍需要获取其数据。我的观点目前不能很好地处理未定义的数据。通过在 getInitialState() 中从 Reflux 存储返回本地存储的缓存,所有连接的组件都将在第一次渲染调用之前获取该数据。

2) 导致页面刷新的原因是什么,为什么不能以与第一次相同的方式加载数据?

这主要是我必须围绕 livereload 构建的一种解决方法,在我进行编辑时刷新页面(稍后会考虑使用 react-hotloader 但还不是一个选项),但用户也可以在我的某个地方点击刷新嵌套视图,这将具有相同的效果。当他们手动刷新时,他们并没有在开始时进入应用程序。

3) 当组件连接到 store 的 change 事件时,为什么不更新呢?

他们确实会更新,但就像我说的那样,他们现在不处理空数据,并且在第一次渲染时,他们会在等待商店获取内容时错过它。我可以让我的所有视图都优雅地处理空数据,但这会增加很多样板代码。

从到目前为止的回复中,我感觉我正在使用 localStorage 做的是常用的方法。在 localStorage 或 sessionStorage 或类似的东西中本地缓存内容,并在刷新后立即提供该数据。

我应该通过在 localStorage 无法正常工作的奇怪情况下优雅地处理空数据来使我的观点更加稳健。

【问题讨论】:

  • 这对于 Stack Overflow 来说感觉有点宽泛(也许是因为它似乎需要一些来回才能得到一个合理的解决方案)。
  • 关于您的实现的一些问题(如果您编辑问题以包含更多详细信息可能会有所帮助)... 1) 为什么要使用getInitialState 中的数据初始化组件? 2) 导致页面刷新的原因是什么,为什么不能以与第一次相同的方式加载数据? 3) 当组件连接到 store 的 change 事件时,为什么不更新呢?
  • 我添加了更多信息
  • 为什么不直接修复渲染方法以不处理数据?
  • 因为就像我说的那样,它添加了相当多的样板代码。但我想没有更好的选择,然后将它添加到我已经使用的模式中。

标签: javascript reactjs react-router refluxjs


【解决方案1】:

当它的 emitChange() 触发时,我一直在 sessionStorage 中缓存每个 Store,如果缓存数据存在,则从 sessionStorage 初始化存储,否则为 null 值。如果视图可以处理空值,这似乎可行,无论如何这可能是一个好主意(听起来这是你的主要问题)。

我建议让您的视图优雅地处理没有数据的情况,如果缓存不可用,则使用空值初始化所有内容,然后在数据返回时调用后端使用 Action 更新空值。

我没有尝试过 Reflux,但在常规 Flux 中它看起来像这样(也许你可以应用相同的原理):

var _data;

if (sessionStorage.PostStore)
  _data = JSON.parse(sessionStorage.PostStore);
else {
  _data = {
    posts: null
  };
  BackendAPI.getPosts(function(err, posts) {
    if (posts) {
      PostActions.setPosts(posts);
    }
  });
}

...

AppDispatcher.register(function(payload) {
  var action = payload.action;

  switch (action.actionType) {

    ...

    case Constants.SET_POSTS:
      _data.posts= action.data.posts;
      break;

    default: 
      return true
  }

  // Update cache because state changed
  sessionStorage.PostStore = JSON.stringify(_data);

  PostStore.emitChange();
  return true;
});

【讨论】:

  • 谢谢,我会接受这个作为答案,因为显然没有其他模式。我已经在这样做了。然后,我将不得不在我的视图中对空数据进行更多检查。
猜你喜欢
  • 2020-12-01
  • 1970-01-01
  • 2018-08-17
  • 2020-07-27
  • 2021-11-19
  • 2020-09-01
  • 2021-04-05
  • 1970-01-01
  • 2021-12-31
相关资源
最近更新 更多