窗口重新加载(客户端)上的Redux状态重置

时间:2017-12-26 18:59:40

标签: javascript reactjs redux local-storage state

我有像userInfo,chatInfo等非常庞大和复杂的对象,如对象&具有非常大和嵌套信息的数组。每当我刷新页面时,就会在我的反应应用程序中重新设置redux状态,我必须再次调用所有这些API。

我对这个话题进行了一些研究。我查看了Dan Abramov关于redux的egghead教程。他所做的是在浏览器的localStorage中维护redux状态,并在每100或500毫秒后更新localStorage。我觉得好像这是一种代码味道。

不断观察localStorage状态并更新它,不会影响浏览器的性能。我的意思是Angular 1失败的原因并不是因为它持续观察状态变量,过了一段时间,如果网站在浏览器中保存,它就会放慢速度。因为我们的脚本不断检查变量的状态。我觉得好像我们在这里做同样的事情。

如果在localStorage中维护redux状态是正确的方法可以有人告诉我为什么这样做?如果没有,是否有更好的方法?

9 个答案:

答案 0 :(得分:6)

我认为在这里使用localStorage是最好的选择,因为在客户端上似乎需要存储的数据。如果数据没有变化,您就不需要反复查询或观看localStorage

您可以做的另一件事是在localStorage周围包裹一个closure,以便在检索您的"大"时不会总是碰到磁盘。数据。每个浏览器都以不同的方式实现localStorage,因此无法保证一致的行为或I / O性能。

这也增加了一个隐藏实现的简单抽象层,并在一个地方控制与用户数据相关的所有内容。

以下是用户个人资料数据关闭的简单示例:

// UserProfile.js
var UserProfile = (function() {
  var userData = {};

  var getUserData = function() {
    if (!userData) { 
      userData = JSON.parse(localStorage.getItem("userData"));
    }
    return userData;
  };

  var setUserData = function(userData) {
    localStorage.setItem("userData", JSON.stringify(userData));
    userData = JSON.parse(localStorage.getItem("userData"));
  };

  return {
    getUserData: getUserData,
    setUserData: setUserData
  }
})();

export default UserProfile;

设置用户数据对象:这将覆盖localStorage,并在闭包内设置局部变量。

import UserProfile from '/UserProfile';
UserProfile.setUserData(newUserData);

获取用户数据对象:这将从闭包内的局部变量中获取数据,否则如果未设置则从localStorage获取。

import UserProfile from '/UserProfile';
var userData = UserProfile.getUserData();

这里的想法是将数据从localStorage加载到内存中,这是第一次加载应用时,或者是第一次API调用。在用户个人资料数据发生变化(例如,用户更新其个人资料)之前,您将再次查询API,并通过UserProfile.setUserData(..)调用再次更新数据。

答案 1 :(得分:5)

问题是你需要在什么时候实现持久性。我觉得你的案例的答案是在页面重新加载。所以如果你担心性能,我会说: *仅在状态更改时更新localStorage。更新状态时在reducer内部。 *在启动应用程序时从localStorage读取。

(这种方式只有在状态发生变化并且只读一次时才会写入)

P.S。 我建议使用https://github.com/rt2zz/redux-persist包来实现Redux应用程序中的持久性。

答案 2 :(得分:5)

我只会将其作为弱缓存而不依赖它。本地存储空间有限(例如Chrome上为5mb),可能无法使用。您必须仔细验证您的数据是否已写入。

正如其他人所说的那样,你不会看到本地存储,你会定期冲洗商店。但我同意,盲目地认为你所有的州都适合坚持本地存储似乎是一个相当粗糙的黑客。与所有缓存解决方案一样,您需要仔细考虑其含义(新鲜度,过期等)。听起来你可能想要逐步做到这一点 - 挑选一些适合缓存的低挂水果,并考虑缓存该状态在本地存储中的含义。

答案 3 :(得分:3)

尝试 redux-persis 你可以做乐观的持久性,与底层平台(网络/移动设备)无关。

如果你仍然发现性能是一个瓶颈。您可以执行以下任一步骤。

缓存中间件

创建一个可以监听更改的中间件并记录它们,但每隔5秒才将它们刷新一次。

将事件处理程序附加到 window.beforeunload 以检测用户导航或关闭浏览器以刷新更改

持久性策略

要保留数据,您可以使用以下两种策略之一。

  • 如果没有性能瓶颈,请将其存储在localStorage中。
  • 将JSON blob发送到服务器,如文件上传。在应用加载并在本地持久存档时获取上次JSON状态。

我建议你开始使用 redux-persist 。如果仍有性能瓶颈,则使用缓存中间件以及两种持久性策略之一。

答案 4 :(得分:2)

我认为在大多数情况下,您希望在某些行动发生后将您的州保留在localStorage。至少在我需要坚持的项目中总是如此。

因此,如果您使用redux-sagaredux-observableredux-cycles来协调您的副作用,您可以很容易地产生副作用(将状态保持为localStorage )只要其中一个动作发生,就会发生。我认为这比基于时间间隔“随机”持久化数据要好得多。

答案 5 :(得分:2)

您对观察状态的理解似乎是您有某种间隔,它将继续检查您的状态并在localStorage中更新它。但是,我认为您可以通过在react生命周期方法componentDidUpdate中更新localStorage来实现同样的目的。每次组件更新时,此方法都会触发,因此您可以利用它并在每次触发时更新localStorage,而不会导致性能下降。

答案 6 :(得分:2)

一种选择是在 INITIAL_STATE

中加载数据
window.__INITIAL_STATE__ = { ...state... }

并加载reducer:

window.__APP_STATE__.__REDUCERS__.push(reducer) 

答案 7 :(得分:2)

在大型redux +反应应用程序中保持状态是完全可以的。

关于angular1,观察者和摘要周期虽然在每个状态发生变化,即使你rehydrate表示由于还原连接API和反应的vrtualDOM而没有呈现所有组件。

您可以查看:

性能不应该是您首要关注的问题。如果要使你的状态正常化并且只保留重要信息,例如草稿等(更少信息 - 更少的补液)。

这种设置的更大问题通常是应用程序中有任何后台同步或套接字更新。拥有多个浏览器选项卡会导致异步写入本地数据库,导致覆盖以前的状态。

这是一个顶部的薄包装,用于交叉表同步redux-persist-crosstab

您可以在mattermost webapp中查看其中一些实现以及它们如何将其用于实时应用。

他们通过一些箍来获得额外的稳定性和性能 - link to store file在mattermost webapp中

答案 8 :(得分:1)

我认为你可以使用名为redux-storage的npm模块。它为redux提供了持久层,具有灵活的后端。您可以将redux-storage与您想要的任何redux-storage-engine结合使用。在我看来,您可以将其与redux-storage-engine-sessionstorage结合使用,假设您只想共享和保存信息,直到浏览器打开。无需使用localStorage膨胀浏览器。您需要额外的JavaScript支持才能明确这一点。

Redux-storage将在每次状态更改后触发加载并保存操作。在加载和保存的情况下提供更多的灵活性。此外,如果您不保存某些状态更改,则定义要过滤掉的状态数组。