问题
Redux是集中管理应用程序状态的一种很好的方法。但是,它有一个小问题:当你重新加载页面时,整个状态会消失(如图3-19所示)。
图3-19:如果页面重新加载(右),Redux状态(左)会丢失
状态丢失是因为Redux将它保存在内存中了,那么我们如何防止状态丢失呢?
解决方案
我们将使用Redux Persist(持久化)库在本地存储中保存Redux状态的副本。要安装Redux Persist,请输入以下命令:
首先,我们通过封装现有reducer,创建一个支持持久化的reducer:
storage变量指定我们将在何处持久保存Redux状态:默认保存在localStorage。根据persistConfig,我们要将状态保存在一个名为persist:root的localStorage项中。当Redux状态改变时,persistedReducer将使用localStorage.setItem('persist:root',...)创建或更新状态副本。现在,我们需要用persistedReducer创建Redux store:
Redux Persist代码需要插在Redux store和访问Redux store的那些代码之间。我们通过一个名为PersistGate的组件来实现:
PersistGate要添加在Redux Provider之内以及将要使用Redux的组件之外。PersistGate会检查Redux状态,如果需要的话,它会从localStorage中重新加载Redux状态。重新加载数据可能需要一点时间,如果你希望在界面上给用户一点类似于“加载中”的提示,那么可以将loading组件传递给PersistGate,以展示一个旋转中的loading动画。当Redux重新加载时,loading组件将显示在它的子组件的位置。如果你不想要loading组件,那么可以把它设为null。
下面是示例应用中修改后的 App.js 的最终版本:
现在,当用户重新加载页面时,Redux状态也不会丢失,如图3-20所示。
图3-20:重新加载前(上)和加载后(下)的Redux状态
讨论
Redux Persist库是能够实现在页面重新加载时保持Redux状态的一个不错的办法。如果Redux的状态数据较多,需要注意不能超过localStorage的最大存储限制,不同浏览器的最大值会有所不同,但通常是10MB左右。所以,如果你的Redux数据大于10MB,那么你可以考虑存放一些到服务器上。
你可以从GitHub网站( https://oreil.ly/K8U5J )下载本解决方案的源代码。