当前位置: 首页 > 软件库 > 大数据 > 数据存储 >

redux-persist

persist and rehydrate a redux store
授权协议 MIT License
开发语言 C#
所属分类 大数据、 数据存储
软件类型 开源软件
地区 不详
投 递 者 宣冥夜
操作系统 跨平台
开源组织
适用人群 未知
 软件概览

Redux Persist

Persist and rehydrate a redux store.

October 15th, 2021 - Move to TypeScript (Thanks @smellman)

As part of the work to upgrade the infrastructure used to build redux-persist, we're moving from Flow to TypeScript.

  • Move from Flow to TypeScript
  • Move from TravisCI to GitHub Actions (.github/workflows/ci.yml)
  • Version updates for some dependencies

September 22nd, 2021 - Under New Management

Redux Persist is a staple project for Redux developers, both on mobile and on the web. If you're here, it's likely because you need it now or have used it before and need to debug something, and like me have possibly struggled with making it work (especially with newer versions of things) and making it work with your code because the examples you'll find around the internet are inconsistent.

I (@ckalika) spoke with @rt2zz about taking over maintenance of the project, and we agreed to give it a shot and see how we go. My priorities are as follows:

  1. Go through and triage the existing issues

    • Separate them into bugs, feature requests, basic questions/requests for code samples, and issues that are either not project-specific or don't fall within the remit of the project (specific definitions and criteria will be posted in the future)
    • Determine the severity/urgency of each bug or feature request
    • Guestimate the size of them
    • Determine which are actionable immediately or in the short term
    • Establish some semblance of test criteria for each
  2. Upgrade dependencies (where possible) so that we've got something building with modern versions

    • Note: Right now, it's about modernising the project infrastructure and build process without making breaking API changes
  3. Go through the existing pull requests

    • Merge the ones that deal with documentation, code samples, etc.
    • Review and merge the ones that deal with open issues
    • Review and merge the ones that will require breaking changes and consult authors about redux-persist@v7 (feature set and requirements to be defined)
  4. Update the documentation

    • Split it out for both web and mobile
    • Providing code samples and test coverage for how to use the library
    • Provide or link to working examples that integrate with additional libraries (e.g. RTK Query).
  5. Improve testing and automation

    • Move to GitHub Actions
    • Move from Ava to Jest

There's a lot to do here, so I'll ask your patience and understanding as I work through it. If you have ideas for how to improve the library, the documentation, or the community, I'd love to hear them, and if you're submitting pull requests (or have submitted some previously), please reach out and help me understand what you're aiming to do with it.

I'll try to get some discussions up to pull together ideas, so we can properly work out what the next version is likely to look like.

September 22nd, 2021 - Under New Management

Redux Persist is a staple project for Redux developers, both on mobile and on the web. If you're here, it's likely because you need it now or have used it before and need to debug something, and like me have possibly struggled with making it work (especially with newer versions of things) and making it work with your code because the examples you'll find around the internet are inconsistent.

I (@ckalika) spoke with @rt2zz about taking over maintenance of the project, and we agreed to give it a shot and see how we go. My priorities are as follows:

  1. Go through and triage the existing issues

    • Separate them into bugs, feature requests, basic questions/requests for code samples, and issues that are either not project-specific or don't fall within the remit of the project (specific definitions and criteria will be posted in the future)
    • Determine the severity/urgency of each bug or feature request
    • Guestimate the size of them
    • Determine which are actionable immediately or in the short term
    • Establish some semblance of test criteria for each
  2. Upgrade dependencies (where possible) so that we've got something building with modern versions

    • Note: Right now, it's about modernising the project infrastructure and build process without making breaking API changes
  3. Go through the existing pull requests

    • Merge the ones that deal with documentation, code samples, etc.
    • Review and merge the ones that deal with open issues
    • Review and merge the ones that will require breaking changes and consult authors about redux-persist@v7 (feature set and requirements to be defined)
  4. Update the documentation

    • Split it out for both web and mobile
    • Providing code samples and test coverage for how to use the library
    • Provide or link to working examples that integrate with additional libraries (e.g. RTK Query).
  5. Improve testing and automation

    • Move to GitHub Actions
    • Move from Ava to Jest

There's a lot to do here, so I'll ask your patience and understanding as I work through it. If you have ideas for how to improve the library, the documentation, or the community, I'd love to hear them, and if you're submitting pull requests (or have submitted some previously), please reach out and help me understand what you're aiming to do with it.

I'll try to get some discussions up to pull together ideas, so we can properly work out what the next version is likely to look like (spoiler: I'm guessing it's going to be in TypeScript instead of Flow).

v6 upgrade

Web: no breaking changesReact Native: Users must now explicitly pass their storage engine in. e.g.

import AsyncStorage from '@react-native-async-storage/async-storage';

const persistConfig = {
  //...
  storage: AsyncStorage
}

Quickstart

npm install redux-persist

Usage Examples:

  1. Basic Usage
  2. Nested Persists
  3. Hot Module Replacement
  4. Code Splitting [coming soon]

Basic Usage

Basic usage involves adding persistReducer and persistStore to your setup. IMPORTANT Every app needs to decide how many levels of state they want to "merge". The default is 1 level. Please read through the state reconciler docs for more information.

// configureStore.js

import { createStore } from 'redux'
import { persistStore, persistReducer } from 'redux-persist'
import storage from 'redux-persist/lib/storage' // defaults to localStorage for web

import rootReducer from './reducers'

const persistConfig = {
  key: 'root',
  storage,
}

const persistedReducer = persistReducer(persistConfig, rootReducer)

export default () => {
  let store = createStore(persistedReducer)
  let persistor = persistStore(store)
  return { store, persistor }
}

If you are using react, wrap your root component with PersistGate. This delays the rendering of your app's UI until your persisted state has been retrieved and saved to redux. NOTE the PersistGate loading prop can be null, or any react instance, e.g. loading={<Loading />}

import { PersistGate } from 'redux-persist/integration/react'

// ... normal setup, create store and persistor, import components etc.

const App = () => {
  return (
    <Provider store={store}>
      <PersistGate loading={null} persistor={persistor}>
        <RootComponent />
      </PersistGate>
    </Provider>
  );
};

API

Full API

persistReducer(config, reducer)

  • arguments
    • config object
      • required config: key, storage
      • notable other config: whitelist, blacklist, version, stateReconciler, debug
    • reducer function
      • any reducer will work, typically this would be the top level reducer returned by combineReducers
  • returns an enhanced reducer

persistStore(store, [config, callback])

  • arguments
    • store redux store The store to be persisted.
    • config object (typically null)
      • If you want to avoid that the persistence starts immediately after calling persistStore, set the option manualPersist. Example: { manualPersist: true } Persistence can then be started at any point with persistor.persist(). You usually want to do this if your storage is not ready when the persistStore call is made.
    • callback function will be called after rehydration is finished.
  • returns persistor object

persistor object

  • the persistor object is returned by persistStore with the following methods:
    • .purge()
      • purges state from disk and returns a promise
    • .flush()
      • immediately writes all pending state to disk and returns a promise
    • .pause()
      • pauses persistence
    • .persist()
      • resumes persistence

State Reconciler

State reconcilers define how incoming state is merged in with initial state. It is critical to choose the right state reconciler for your state. There are three options that ship out of the box, let's look at how each operates:

  1. hardSet (import hardSet from 'redux-persist/lib/stateReconciler/hardSet')This will hard set incoming state. This can be desirable in some cases where persistReducer is nested deeper in your reducer tree, or if you do not rely on initialState in your reducer.
    • incoming state: { foo: incomingFoo }
    • initial state: { foo: initialFoo, bar: initialBar }
    • reconciled state: { foo: incomingFoo } // note bar has been dropped
  2. autoMergeLevel1 (default)This will auto merge one level deep. Auto merge means if the some piece of substate was modified by your reducer during the REHYDRATE action, it will skip this piece of state. Level 1 means it will shallow merge 1 level deep.
    • incoming state: { foo: incomingFoo }
    • initial state: { foo: initialFoo, bar: initialBar }
    • reconciled state: { foo: incomingFoo, bar: initialBar } // note incomingFoo overwrites initialFoo
  3. autoMergeLevel2 (import autoMergeLevel2 from 'redux-persist/lib/stateReconciler/autoMergeLevel2')This acts just like autoMergeLevel1, except it shallow merges two levels
    • incoming state: { foo: incomingFoo }
    • initial state: { foo: initialFoo, bar: initialBar }
    • reconciled state: { foo: mergedFoo, bar: initialBar } // note: initialFoo and incomingFoo are shallow merged

Example

import hardSet from 'redux-persist/lib/stateReconciler/hardSet'

const persistConfig = {
  key: 'root',
  storage,
  stateReconciler: hardSet,
}

React Integration

Redux persist ships with react integration as a convenience. The PersistGate component is the recommended way to delay rendering until persistence is complete. It works in one of two modes:

  1. loading prop: The provided loading value will be rendered until persistence is complete at which point children will be rendered.
  2. function children: The function will be invoked with a single bootstrapped argument. When bootstrapped is true, persistence is complete and it is safe to render the full app. This can be useful for adding transition animations.

Blacklist & Whitelist

By Example:

// BLACKLIST
const persistConfig = {
  key: 'root',
  storage: storage,
  blacklist: ['navigation'] // navigation will not be persisted
};

// WHITELIST
const persistConfig = {
  key: 'root',
  storage: storage,
  whitelist: ['navigation'] // only navigation will be persisted
};

Nested Persists

Nested persist can be useful for including different storage adapters, code splitting, or deep filtering. For example while blacklist and whitelist only work one level deep, but we can use a nested persist to blacklist a deeper value:

import { combineReducers } from 'redux'
import { persistReducer } from 'redux-persist'
import storage from 'redux-persist/lib/storage'

import { authReducer, otherReducer } from './reducers'

const rootPersistConfig = {
  key: 'root',
  storage: storage,
  blacklist: ['auth']
}

const authPersistConfig = {
  key: 'auth',
  storage: storage,
  blacklist: ['somethingTemporary']
}

const rootReducer = combineReducers({
  auth: persistReducer(authPersistConfig, authReducer),
  other: otherReducer,
})

export default persistReducer(rootPersistConfig, rootReducer)

Migrations

persistReducer has a general purpose "migrate" config which will be called after getting stored state but before actually reconciling with the reducer. It can be any function which takes state as an argument and returns a promise to return a new state object.

Redux Persist ships with createMigrate, which helps create a synchronous migration for moving from any version of stored state to the current state version. [Additional information]

Transforms

Transforms allow you to customize the state object that gets persisted and rehydrated.

There are several libraries that tackle some common implementations for transforms.

  • immutable - support immutable reducers
  • seamless-immutable - support seamless-immutable reducers
  • compress - compress your serialized state with lz-string
  • encrypt - encrypt your serialized state with AES
  • filter - store or load a subset of your state
  • filter-immutable - store or load a subset of your state with support for immutablejs
  • expire - expire a specific subset of your state based on a property
  • expire-reducer - more flexible alternative to expire transformer above with more options

When the state object gets persisted, it first gets serialized with JSON.stringify(). If parts of your state object are not mappable to JSON objects, the serialization process may transform these parts of your state in unexpected ways. For example, the javascript Set type does not exist in JSON. When you try to serialize a Set via JSON.stringify(), it gets converted to an empty object. Probably not what you want.

Below is a Transform that successfully persists a Set property, which simply converts it to an array and back. In this way, the Set gets converted to an Array, which is a recognized data structure in JSON. When pulled out of the persisted store, the array gets converted back to a Set before being saved to the redux store.

import { createTransform } from 'redux-persist';

const SetTransform = createTransform(
  // transform state on its way to being serialized and persisted.
  (inboundState, key) => {
    // convert mySet to an Array.
    return { ...inboundState, mySet: [...inboundState.mySet] };
  },
  // transform state being rehydrated
  (outboundState, key) => {
    // convert mySet back to a Set.
    return { ...outboundState, mySet: new Set(outboundState.mySet) };
  },
  // define which reducers this transform gets called for.
  { whitelist: ['someReducer'] }
);

export default SetTransform;

The createTransform function takes three parameters.

  1. An "inbound" function that gets called right before state is persisted (optional).
  2. An "outbound" function that gets called right before state is rehydrated (optional).
  3. A config object that determines which keys in your state will be transformed (by default no keys are transformed).

In order to take effect transforms need to be added to a PersistReducer’s config object.

import storage from 'redux-persist/lib/storage';
import { SetTransform } from './transforms';

const persistConfig = {
  key: 'root',
  storage: storage,
  transforms: [SetTransform]
};

Storage Engines

Community & Contributing

I will be updating this section shortly. If you have a pull request that you've got outstanding, please reach out and I will try to review it and get it integrated. As we've shifted to TypeScript, that may necessitate some changes, but I'm happy to help in that regard, wherever I can.

  • React-cli使用Redux以及使用redux-persist处理刷新页面redux中全局数据丢失的问题 写在前面:项目基于 react + typescript + react-router + antd + redux + redux-persist React-create-app中使用Redux 首先目录结构如下 | -- src | -- pages | -- Home

  • 1. 全局数据持久化存储的需求: 在React项目中,我们经常会通过redux以及react-redux来存储和管理全局数据。但是通过redux存储全局数据时,会有这么一个问题,如果用户刷新了网页,那么我们通过redux存储的全局数据就会被全部清空,比如登录信息等。 2. 引出: 这个时候,我们就会有全局数据持久化存储的需求。首先我们想到的就是localStorage,localStorage是没

  • 在React项目实际开发中,我们常常会对一些数据进行存储缓存中,防止用户刷新浏览器,数据丢失问题,比如token,用户信息之类的。之前都是手写一遍localStorage和sessionStorage储存,接来下,我们通过一个插件redux-persist配置项,来存储数据。 存储数据配置 首先安装 redux-persist插件 cnpm install redux-persist store

  • redux-persist插件 配置store.ts import { createStore } from 'redux'; import {AllReducers} from './reducers/index'; /引入持久化储存插件 import {persistStore, persistReducer} from 'redux-persist'; // 本地储存 // import s

  • 一、创建 store 仓库(数据持久化) store 入口文件(redux/index.js) // 导入各个模块的 reducer import global from './modules/global/reducer'; import auth from './modules/auth/reducer'; import { persistStore, persistReducer } fr

  • 项目中依赖版本 json "react-redux": "^8.0.5", "@reduxjs/toolkit": "^1.9.1", "redux-persist": "^6.0.0", 默认玩法 tsx import { configureStore } from '@reduxjs/toolkit' import { userSlice } from './slices/user'; imp

  • 因为刷新会导致数据的丢失,相比于vue直接监听浏览器的刷新,react中可以通过redux-persist持久化数据存储 sudo yarn add redux-persist --save store/index.js:(里面接入了react-redux调试工具) // 引入 creatStore 创建store import { createStore } from 'redux' impor

  • 为什么要用 redux-persist redux-persist是一个持久化存储state的插件,那么为什么要用它呢?持久化对于前端开发有什么好处? 2个问题可以一起回答: redux的store状态树保存的state并不是持久保存的,state只是一个内存机制,而我们知道,本地数据库或者像localstorage之类的缓存系统才有可能长时间保存数据,而redux-persist可以让你的数据从

  • registerUser: function (user, success, fail) { API.registerUser(user, function(userServer){ var localUser = UserLocalStorage.serverUserToLocalUser(userServer); UserLocalStorage.

  • redux-persist Storage has always been an integral part of building apps. While building a webapp for our company, I needed a way to persist my states in storage which was reliable, easy to use, and co

  • 今天我将redux合并redux以后发现每次调用store更新状态store会调用所有的reducer来,恰巧我将reducer的default 返回了一个false 。导致我在保存过程中一直给我存我default返回的数据希望大家不要采坑 Store源码 import {createStore, combineReducers, applyMiddleware} from 'redux' imp

  •   redux-persist作用是将store中的数据缓存到浏览器中,减少数据请求,每当白名单中的数据发生变化,才会进行一次更新缓存的操作,并且这个数据缓存是存在localStorage中的,不是会话级别的缓存。   安装方式两种:npm install --save redux-persist / yarn add redux-persist   实现方式主要是依靠两个方法:persistSt

 相关资料
  • 问题内容: 我正在使用React + Flux。我们的团队计划从助焊剂转变为还原剂。Redux对于来自助焊剂世界的我非常困惑。在 磁通控制中, 从 **组件- 操作->存储和存储更新返回组件 很** 简单。它很简单,也很清楚。 但在redux中令人困惑。这里没有商店,是的,有些例子没有使用商店。我经历了一些教程,看来每个人都有自己的实现风格。有些正在使用容器,有些则没有。(我不知道这个Contai

  • 对于如何使用React路由器的。 换句话说,如果您使用Redux的连接一个组件,那么如何放置应该在调度特定操作后触发的按钮? 为了澄清这个问题,这里是我的一个实验片段。。。 如您所见,一旦通过将帖子添加到Redux的状态,页面就需要通过历史记录移动到。推 根据Redux的文档,容器用于更新状态(以及获取数据)。因此,哑组件不应该放置任何类似。 有什么方法比上面的代码更好? 如有任何建议,将不胜感激

  • Dan Abramov 在 React Europe 2015 上作了一场令人印象深刻的演示 Hot Reloading with Time Travel,之后 Redux 迅速成为最受人关注的 Flux 实现之一。 Redux 把自己标榜为一个“可预测的状态容器”,其实也是 Flux 里面“单向数据流”的思想,只是它充分利用函数式的特性,让整个实现更加优雅纯粹,使用起来也更简单。 Redux(o

  • Redux 是 JavaScript 应用程序的可预测状态容器。(不要与WordPress框架——Redux框架混淆。) 它可以帮助您编写行为一致、在不同环境(客户机、服务器和本机)中运行且易于测试的应用程序。除此之外,它还提供了很好的开发体验,例如实时代码编辑和时间旅行调试器的结合。 您可以将 Redux 与 React 一起使用,或与任何其他视图库一起使用。 Actions: // Still

  • 本文向大家介绍redux Redux-thunk:基础知识,包括了redux Redux-thunk:基础知识的使用技巧和注意事项,需要的朋友参考一下 示例 虽然redux本身是完全同步的,但是您可以使用中间件redux-thunk来处理异步操作。 “ thunk”是回调的另一个名称。该函数通常作为参数传递,以便以后调用。 要使用,请将中间件应用于您的redux存储: 这使您可以将thunk传递给

  • 本文向大家介绍一篇文章介绍redux、react-redux、redux-saga总结,包括了一篇文章介绍redux、react-redux、redux-saga总结的使用技巧和注意事项,需要的朋友参考一下 本篇主要将react全家桶的产品非常精炼的提取了核心内容,精华程度堪比精油。各位大人,既然来了,客官您坐,来人,给客官看茶~~ redux 前言 首先,本篇文章要求您对js,react等知识有

  • 目录 为何组件没有被重新渲染、或者 mapStateToProps 没有运行? 为何组件频繁的重新渲染? 怎样使 mapStateToProps 执行更快? 为何不在被连接的组件中使用 this.props.dispatch ? 应该只连接到顶层组件吗,或者可以在组件树中连接到不同组件吗? React Redux 为何组件没有被重新渲染、或者 mapStateToProps 没有运行? 目前来看,

  • An implementation of the @handsontable/react component with a readOnly toggle switch and the Redux state manager implemented.import React from 'react'; import ReactDOM from 'react-dom'; import {create