Javascript 在页面刷新时响应路由和持久性

Javascript 在页面刷新时响应路由和持久性,javascript,reactjs,react-router,refluxjs,Javascript,Reactjs,React Router,Refluxjs,我使用React with React router和Reflech作为数据存储,但我不确定如何最好地处理持久性以允许页面刷新 My components使用reflow.connect连接到存储,但由于存储从后端获取数据,因此在组件首次初始化和呈现时,它还不可用 当用户从一开始就进入我的应用程序时,所有这些数据都会按顺序加载,并在需要时可用,但如果沿着某条路径进一步触发页面刷新,react会尝试呈现依赖于尚未存在的数据的组件 我通过不断在LocalStorage中保存一份数据副本并从回流存储g

我使用React with React router和Reflech作为数据存储,但我不确定如何最好地处理持久性以允许页面刷新

My components使用reflow.connect连接到存储,但由于存储从后端获取数据,因此在组件首次初始化和呈现时,它还不可用

当用户从一开始就进入我的应用程序时,所有这些数据都会按顺序加载,并在需要时可用,但如果沿着某条路径进一步触发页面刷新,react会尝试呈现依赖于尚未存在的数据的组件

我通过不断在LocalStorage中保存一份数据副本并从回流存储getInitialState()中提供该副本来解决这个问题,这样所有组件都可以在呈现之前获取数据

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

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

------编辑----- 要回答WiredPairie的评论:

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

当我的组件使用reflow.connect时,它们在第一次渲染时还没有数据处于其状态,因为存储仍然需要获取其数据。我的视图当前无法正常处理未定义的数据。通过从getInitialState()中的回流存储返回本地存储的缓存,所有连接的组件将在第一次渲染调用之前获取该数据

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

这主要是我不得不围绕livereload构建的一个解决方案,在我进行编辑时刷新页面(稍后将研究使用react hotloader,但还不是一个选项),但用户也可以在嵌套视图中的某个位置点击刷新,这将产生相同的效果。当他们手动刷新时,他们不会在开始时进入应用程序

3) 当组件连接到存储的更改事件时,为什么不更新它们

它们确实会更新,但正如我所说的,它们现在不处理空数据,在第一次渲染时,它们会在等待存储获取数据时丢失数据。我可以使用空数据使所有视图正常工作,但这会添加大量样板代码

从到目前为止的回复中,我感觉使用localStorage是实现这一点的常用方法。在本地存储或会话存储或类似的地方缓存内容,并在刷新后立即提供该数据


我应该在本地存储无法正常工作的奇怪情况下优雅地处理空数据,从而使我的视图更加健壮。

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

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

我没有尝试过回流,但在常规流量下,它看起来是这样的(也许你可以应用相同的原理):


对于堆栈溢出来说,这感觉有点宽泛(可能是因为它似乎需要来回一些才能得到一个合理的解决方案)。关于您的实现的一些问题(如果您编辑该问题以包含更多细节,可能会有所帮助)。。。1) 为什么要用
getInitialState
中的数据初始化组件?2) 是什么导致页面刷新?为什么不能以与第一次相同的方式加载数据?3) 当组件连接到存储的更改事件时,为什么它们不更新呢?我添加了更多的信息为什么不修复渲染方法来处理任何数据?因为正如我所说,它添加了相当多的样板代码。但是我想没有更好的选择可以将它添加到我已经使用的模式中。谢谢,我会接受这个作为答案,因为显然没有其他模式。我已经这样做了。我将不得不在我的视图中做更多的空数据检查。
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;
});