Security News
GitHub Removes Malicious Pull Requests Targeting Open Source Repositories
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
redux-persist
Advanced tools
redux-persist is a library that allows you to save the Redux store in persistent storage, such as local storage, session storage, or even custom storage engines. This helps in maintaining the state of the application across page reloads.
Persisting Redux State
This feature allows you to persist the Redux state using a storage engine like local storage. The `persistReducer` function wraps your root reducer, and `persistStore` initializes the persistor.
const persistConfig = { key: 'root', storage }; const persistedReducer = persistReducer(persistConfig, rootReducer); const store = createStore(persistedReducer); const persistor = persistStore(store);
Rehydrating State
Rehydration is the process of loading the persisted state back into the Redux store when the application starts. This ensures that the state is restored to its previous state before the page was reloaded.
persistStore(store, null, () => { console.log('Rehydration complete'); });
Custom Storage Engines
You can use custom storage engines if the default local storage or session storage does not meet your requirements. This example shows how to create a noop storage engine for environments where local storage is not available.
import createWebStorage from 'redux-persist/lib/storage/createWebStorage'; const createNoopStorage = () => { return { getItem(_key) { return Promise.resolve(null); }, setItem(_key, value) { return Promise.resolve(value); }, removeItem(_key) { return Promise.resolve(); } }; }; const storage = typeof window !== 'undefined' ? createWebStorage('local') : createNoopStorage();
redux-localstorage is another library that allows you to persist Redux state to local storage. It is similar to redux-persist but offers a more modular approach, allowing you to choose different storage adapters and serializers.
redux-persist-transform-encrypt is a transformer for redux-persist that encrypts your persisted state. This is useful if you need to store sensitive information securely. It works as an add-on to redux-persist, providing encryption capabilities.
redux-persist-cookie-storage is a storage engine for redux-persist that uses cookies instead of local storage or session storage. This can be useful for server-side rendering or when you need to share state across different subdomains.
Persist and rehydrate a redux store.
Redux Persist takes your redux state object and saves it to persisted storage. On app launch, it retrieves this persisted state and saves it back to redux.
Note: These instructions are for redux-persist v5. For a list of breaking changes between v4 and v5, see our migration guide. v4 will be supported for the forseeable future, and if it works well for your use case you are encouraged to stay on v4.
npm install redux-persist
Basic implementation 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'
import rootReducer from './reducers'
const persistConfig = {
key: 'root',
storage: 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 React from 'react'
import { Provider } from 'react-redux'
import { PersistGate } from 'redux-persist/lib/integration/react'
import configureStore from './store/configureStore'
let { store, persistor } = configureStore()
// import your necessary custom components.
import { RootComponent } from './components'
const App = () => {
return (
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<RootComponent />
</PersistGate>
</Provider>
);
};
export default App
persistReducer(config, reducer)
key, storage
whitelist, blacklist, version, stateReconciler, debug
combineReducers
persistStore(store, [config, callback])
persistor object
.purge(keys)
flush()
pause()
persist()
State reconcilers define how incoming persisted state is merged in with existing default state. It is critical to choose the right state reconciler for your state shape. There are three options that ship out of the box, lets look at how each operates:
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.
{ foo: incomingFoo }
{ foo: initialFoo, bar: initialBar }
{ foo: incomingFoo }
// note bar has been dropped{ foo: incomingFoo }
{ foo: initialFoo, bar: initialBar }
{ foo: incomingFoo, bar: initialBar }
{ foo: incomingFoo }
{ foo: initialFoo, bar: initialBar }
{ foo: mergedFoo, bar: initialBar }
import hardSet from 'redux-persist/lib/stateReconciler/hardSet'
const persistConfig = {
key: 'root',
storage,
stateReconciler: hardSet,
}
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
};
The blacklist and whitelist only work one level deep. However persisted reducers can be nested.For example, if you want to blacklist state.auth.somethingTemporary
:
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)
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 of the 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.
const myTransform = 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'] }
);
The createTransform function takes three parameters.
import storage from 'redux-persist/lib/storage'
import sessionStorage from 'redux-persist/lib/storage/session'
import storage from 'redux-persist/lib/storage'
setItem
getItem
removeItem
. (NB: These methods must support promises)FAQs
persist and rehydrate redux stores
The npm package redux-persist receives a total of 447,166 weekly downloads. As such, redux-persist popularity was classified as popular.
We found that redux-persist demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
Security News
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
Security News
Node.js will be enforcing stricter semver-major PR policies a month before major releases to enhance stability and ensure reliable release candidates.