Gathering detailed insights and metrics for reduxjs-toolkit-persist
Gathering detailed insights and metrics for reduxjs-toolkit-persist
Gathering detailed insights and metrics for reduxjs-toolkit-persist
Gathering detailed insights and metrics for reduxjs-toolkit-persist
persist-redux-slice
Automatically persist a redux slice in localStorage.
expo-router-redux-template
An expo template featuring expo-router, reduxjs-toolkit, react-native-reanimated, and redux-persist for cross-platform mobile app development.
@photobot/reduxjs-toolkit-persist
persist and rehydrate redux stores
npm install reduxjs-toolkit-persist
Typescript
Module System
Node Version
NPM Version
59.6
Supply Chain
98.4
Quality
75.5
Maintenance
100
Vulnerability
100
License
TypeScript (95.71%)
JavaScript (4.29%)
Total Downloads
934,068
Last Day
1,531
Last Week
8,292
Last Month
33,171
Last Year
417,891
32 Stars
887 Commits
9 Forks
1 Watching
27 Branches
1 Contributors
Minified
Minified + Gzipped
Latest Version
7.2.1
Package Id
reduxjs-toolkit-persist@7.2.1
Unpacked Size
379.96 kB
Size
91.51 kB
File Count
109
NPM Version
8.1.2
Node Version
16.13.2
Cumulative downloads
Total Downloads
Last day
13.1%
1,531
Compared to previous day
Last week
-2%
8,292
Compared to previous week
Last month
13.2%
33,171
Compared to previous month
Last year
23.3%
417,891
Compared to previous year
1
26
Persist and rehydrate a redux store. This is a fork of redux-persist that implements @reduxjs/toolkit (replacing the core redux dependency) as well as upgrading various dependencies to more recent versions.
Web: no breaking changes React Native: Users must now explicitly pass their storage engine in. e.g.
1import AsyncStorage from '@react-native-async-storage/async-storage'; 2 3const persistConfig = { 4 //... 5 storage: AsyncStorage 6}
npm install reduxjs-toolkit-persist
Usage Examples:
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.
1// configureStore.js 2 3import { createStore } from '@reduxjs/toolkit' 4import { persistStore, persistReducer } from 'reduxjs-toolkit-persist' 5import storage from 'reduxjs-toolkit-persist/lib/storage' // defaults to localStorage for web 6 7import rootReducer from './reducers' 8 9const persistConfig = { 10 key: 'root', 11 storage, 12} 13 14const persistedReducer = persistReducer(persistConfig, rootReducer) 15 16export default () => { 17 let store = createStore(persistedReducer) 18 let persistor = persistStore(store) 19 return { store, persistor } 20}
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 />}
1import { PersistGate } from 'reduxjs-toolkit-persist/integration/react' 2 3// ... normal setup, create store and persistor, import components etc. 4 5const App = () => { 6 return ( 7 <Provider store={store}> 8 <PersistGate loading={null} persistor={persistor}> 9 <RootComponent /> 10 </PersistGate> 11 </Provider> 12 ); 13};
Redux Toolkit gives us more options. This example will use createSlice and configureStore.
1// reducers/count.ts 2 3import {createSlice} from '@reduxjs/toolkit'; 4 5export interface CountState { 6 count: number 7}; 8 9const defaultState : CountState = { 10 count: 0, 11}; 12 13const slice = createSlice({ 14 name: 'count', 15 initialState: defaultState, 16 reducers: { 17 increment: (state: CountState, action) => { 18 state.count++; 19 }, 20 decrement: (state: CountState, action) => { 21 state.count--; 22 } 23 } 24}); 25 26export const { increment, decrement } = slice.actions; 27 28export default slice.reducer;
1// store.js 2 3import { combineReducers, configureStore, getDefaultMiddleware } from '@reduxjs/toolkit'; 4import { persistReducer, persistStore, FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER } from 'reduxjs-toolkit-persist'; 5import storage from 'reduxjs-toolkit-persist/lib/storage' 6import autoMergeLevel1 from 'reduxjs-toolkit-persist/lib/stateReconciler/autoMergeLevel1'; 7import countReducer from './reducers/count'; 8import anotherReducer from './reducers/another'; 9 10const persistConfig = { 11 key: 'root', 12 storage: storage, 13 stateReconciler: autoMergeLevel1, 14}; 15 16const reducers = combineReducers({ 17 count: countReducer, 18 another: anotherReducer 19}); 20 21const _persistedReducer = persistReducer(persistConfig, reducers); 22 23export const store = configureStore({ 24 reducer: _persistedReducer, 25 middleware: getDefaultMiddleware({ 26 serializableCheck: { 27 /* ignore persistance actions */ 28 ignoredActions: [ 29 FLUSH, 30 REHYDRATE, 31 PAUSE, 32 PERSIST, 33 PURGE, 34 REGISTER 35 ], 36 }, 37 }), 38});
As an alternative to using combineReducers
followed by persistReducer
, you can use a single call to persistCombineReducers
like so:
1import { persistCombineReducers } from 'reduxjs-toolkit-persist'
2
3const _persistedReducer = persistCombineReducers(
4 persistConfig,
5 {
6 count: countReducer,
7 another: anotherReducer
8 }
9);
Note: persistCombineReducers
defaults to the autoMergeLevel2
State Reconciler.
persistReducer(config, reducer)
key, storage
whitelist, blacklist, version, stateReconciler, debug
combineReducers
persistStore(store, [config, callback])
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.persistor object
.purge()
.flush()
.pause()
.persist()
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:
import hardSet from 'reduxjs-toolkit-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.
{ foo: incomingFoo }
{ foo: initialFoo, bar: initialBar }
{ foo: incomingFoo }
// note bar has been dropped{ foo: incomingFoo }
{ foo: initialFoo, bar: initialBar }
{ foo: incomingFoo, bar: initialBar }
// note incomingFoo overwrites initialFooimport autoMergeLevel2 from 'reduxjs-toolkit-persist/lib/stateReconciler/autoMergeLevel2'
)
This acts just like autoMergeLevel1, except it shallow merges two levels
{ foo: incomingFoo }
{ foo: initialFoo, bar: initialBar }
{ foo: mergedFoo, bar: initialBar }
// note: initialFoo and incomingFoo are shallow merged1import hardSet from 'reduxjs-toolkit-persist/lib/stateReconciler/hardSet' 2 3const persistConfig = { 4 key: 'root', 5 storage, 6 stateReconciler: hardSet, 7}
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:
loading
prop: The provided loading value will be rendered until persistence is complete at which point children will be rendered.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.By Example:
1// DENYLIST 2const persistConfig = { 3 key: 'root', 4 storage: storage, 5 blacklist: ['navigation'] // navigation will not be persisted 6}; 7 8// ALLOWLIST 9const persistConfig = { 10 key: 'root', 11 storage: storage, 12 whitelist: ['navigation'] // only navigation will be persisted 13};
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:
1import { combineReducers } from '@reduxjs/toolkit' 2import { persistReducer } from 'reduxjs-toolkit-persist' 3import storage from 'reduxjs-toolkit-persist/lib/storage' 4 5import { authReducer, otherReducer } from './reducers' 6 7const rootPersistConfig = { 8 key: 'root', 9 storage: storage, 10 blacklist: ['auth'] 11} 12 13const authPersistConfig = { 14 key: 'auth', 15 storage: storage, 16 blacklist: ['somethingTemporary'] 17} 18 19const rootReducer = combineReducers({ 20 auth: persistReducer(authPersistConfig, authReducer), 21 other: otherReducer, 22}) 23 24export default persistReducer(rootPersistConfig, rootReducer)
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 allow you to customize the state object that gets persisted and rehydrated.
There are several libraries that tackle some common implementations for transforms.
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.
1import { createTransform } from 'reduxjs-toolkit-persist';
2
3const SetTransform = createTransform(
4 // transform state on its way to being serialized and persisted.
5 (inboundState, key) => {
6 // convert mySet to an Array.
7 return { ...inboundState, mySet: [...inboundState.mySet] };
8 },
9 // transform state being rehydrated
10 (outboundState, key) => {
11 // convert mySet back to a Set.
12 return { ...outboundState, mySet: new Set(outboundState.mySet) };
13 },
14 // define which reducers this transform gets called for.
15 { whitelist: ['someReducer'] }
16);
17
18export default SetTransform;
The createTransform
function takes three parameters.
In order to take effect transforms need to be added to a PersistReducer
’s config object.
1import storage from 'reduxjs-toolkit-persist/lib/storage'; 2import { SetTransform } from './transforms'; 3 4const persistConfig = { 5 key: 'root', 6 storage: storage, 7 transforms: [SetTransform] 8};
<<<<<<< HEAD
import storage from 'reduxjs-toolkit-persist/lib/storage'
import storageSession from 'reduxjs-toolkit-persist/lib/storage/session'
import AsyncStorage from '@react-native-community/async-storage'
import storage from 'redux-persist/lib/storage'
import storageSession from 'redux-persist/lib/storage/session'
d8b01a085e3679db43503a3858e8d4759d6f22fa
setItem
getItem
removeItem
. (NB: These methods must support promises)=======
setItem
getItem
removeItem
. (NB: These methods must support promises)d8b01a085e3679db43503a3858e8d4759d6f22fa
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.
No vulnerabilities found.
Reason
no dangerous workflow patterns detected
Reason
no binaries found in the repo
Reason
license file detected
Details
Reason
8 existing vulnerabilities detected
Details
Reason
Found 0/16 approved changesets -- score normalized to 0
Reason
detected GitHub workflow tokens with excessive permissions
Details
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
dependency not pinned by hash detected -- score normalized to 0
Details
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
Reason
project is not fuzzed
Details
Reason
branch protection not enabled on development/release branches
Details
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
Score
Last Scanned on 2024-12-16
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More