Hi rt2zz~
I want to click one button to clear the storage cache in ReactNative, I used PersistGate but I don't know how to invoke the purge method in the RN component. Could you please explain how to invoke purge method when the onPress event occurs锛烼hx a lot!!
The code is as following:
import * as React from 'react';
import { Provider } from 'react-redux';
import { PersistGate } from 'redux-persist/es/integration/react';
import IntlComponent from './IntlComponent';
import configureStore from './middlewares';
import {View,Text} from 'react-native';
const { persistor, store } = configureStore();
const onBeforeLift = () => {
// take some action before the gate lifts
}
export default class App extends React.Component {
render() {
return
persistor={persistor}
loading={
}
}
Hi @landpy, did you figure this out ?
You should be able to dispatch a PURGE action to the store and this will invoke the purgeStoredState method. Rough example below:
Reducer:
import { PURGE, REHYDRATE } from 'redux-persist';
function myReducer(state = {}, action) {
switch(action.type) {
// [....Your other reducer actions...]
REHYDRATE: // This added just to show that this action type also exists, can be omitted.
console.log("REHYDRATING!!!!");
return state;
PURGE:
console.log("PURGING!!!!");
return {}; // Return the initial state of this reducer to 'reset' the app
}
}
Test Component:
import React from "react";
import { PURGE } from 'redux-persist';
// Generate <TestComponent /> with a button that will purge the persisted store
class TestComponent extends React.Component {
constructor(props) {
super(props);
}
onPurgeStoredState(e) {
e.PreventDefault();
const { dispatch } = this.props; // Grab a ref to the mapped dispatch method
// Create and dispatch the action which will cause redux-persist to purge
dispatch({
type: PURGE,
key: "myStorageKey", // Whatever you chose for the "key" value when initialising redux-persist in the **persistCombineReducers** method - e.g. "root"
result: () => null // Func expected on the submitted action.
});
}
render() {
return(<button onClick={this.onPurgeStoredState.bind(this)}></button>);
}
}
function mapStateToProps(
state,
ownProps
) {
return state;
}
function mapDispatchToProps(
dispatch
) {
return { dispatch }; // Map dispatch method to this.props.dispatch
}
export default connect(mapStateToProps, mapDispatchToProps)(TestComponent);
Wire in the reducer and test component into your app and you should (hopefully) find when you click the button, the store is cleared and messages are logged to the console.
@landpy apologize for taking so long to get around to this. There are a few approaches here depending on your needs.
purgeStoredState to purge state. import { purgeStoredState } from 'redux-persist'persistor.purge() in order to purge state. This is nice because it does not require config as an argument.@rt2zz i landed here accidentally after hours of google searching on why redux-persist wasn't persisting to my local storage a state change in session reducer after user was logged out. During logged out i just cleared the session to the initial state (without mutating of course), but redux-persist didn't appear to persist the newly blank values into local storage and hence... on a refresh the auto rehydrate would bring back the values as if the user was still logged in.
I can of course confirm that persisting was working because inspecting the local storage, the values were there saved. Do you know why this happens ? Version 5. I was expecting all changes on the reducer to be persisted immediately. Of course i ended up using your alternative 2 solution, but i'm curious anyway
Regards
@tommyalvarez Hi Tommy, I'm facing the same situation as you. I'm clearing the session on log out. Did you end up just calling persistor.purge() on log out?
@Kevin-Do Yup, that did the trick. Everything's working like a charm now. I clean the session in redux + purge, because purge will only clean the localstorage.
@tommyalvarez Awesome, thanks!
you can use this:
import { persistStore } from 'redux-persist';
and anywhere you want:
persistStore(this.props).purge();
After more googling and checking the redux-persist documentation (on v5), i updated my project following strictly how to initiaize this library and i did not have to manually purge nothing else anymore. It's now working out of the box for me. So guideline rule: If you are manually calling purge or persist, or triggering action creators of the lib by hand... you're doing something wrong setting it up.
@tommyalvarez could you provide an example showing how you're setting up everything?
Currently I'm facing the exact same issue you were having and I thought calling the persistor.purge() method was an ok alternative.
@bruno-edo sure, here it goes:
_main.js_ => Where all starts in my client-side app
import React from 'react'
import ReactDOM from 'react-dom'
import createStore from './store/createStore'
import { hot } from 'react-hot-loader'
import AppContainer from './containers/AppContainer'
import { persistStore } from 'redux-persist'
// ========================================================
// Store Instantiation
// ========================================================
const initialState = window.___INITIAL_STATE__
const { history, store } = createStore(initialState) // => **Magic configuration of redux-persist happens inside here, check out below in createStore.js**
// begin periodically persisting the store
let persistor = persistStore(store)
store.persistor = persistor
// code ommited for brevity... here goes the initialization of the AppContainer with the ReactDom.render seen in every react-create-app tutorial
_createStore.js_:
import { applyMiddleware, compose, combineReducers, createStore } from 'redux'
import thunk from 'redux-thunk'
import { apiMiddleware } from 'redux-api-middleware'
import { createLogger } from 'redux-logger'
import makeRootReducer from './reducers'
import { routerMiddleware } from 'react-router-redux'
// I18n
import { syncTranslationWithStore, loadTranslations, setLocale } from 'react-redux-i18n'
import { translationsObject } from 'translations/index'
// Router history
import createHistory from 'history/createBrowserHistory'
// Raven for Sentry
import Raven from 'raven-js'
import createRavenMiddleware from 'raven-for-redux'
import { persistReducer } from 'redux-persist'
import storage from 'redux-persist/lib/storage'
import { createBlacklistFilter } from 'redux-persist-transform-filter'
import immutableTransform from 'redux-persist-transform-immutable'
// Do not persist unauthorized param of session state, this is custom for my project not needed
export const saveSubsetBlacklistFilter = createBlacklistFilter(
'session',
['unauthorized', 'loading']
)
export const persistConfig = {
key: 'root_key',
storage,
whitelist: ['session'],
transforms: [saveSubsetBlacklistFilter, immutableTransform()], // Im using immutable in sub reducers so... need this
debug: true
}
export default (initialState = {}) => {
// ... unrelated code ommited for brevity, middlewares and such.
// ** check makeRootReducer also! has more redux-persist config **
const persistedReducer = persistReducer(persistConfig, combineReducers(makeRootReducer()))
// =====================================================
// Store Instantiation and HMR Setup
// =====================================================
const store = createStore(
persistedReducer,
initialState,
composeEnhancers(
applyMiddleware(...middleware),
...enhancers
)
)
store.asyncReducers = {}
// DEPRECATED in react-router v4: To unsubscribe, invoke `store.unsubscribeHistory()` anytime
// store.unsubscribeHistory = browserHistory.listen(updateLocation(store))
// Critical if you have react-hot-loader and webpack v4.
if (module.hot) {
module.hot.accept('./reducers', () => {
const nextRootReducer = makeRootReducer(store.asyncReducers)
store.replaceReducer(persistReducer(persistConfig, combineReducers(nextRootReducer)))
})
}
syncTranslationWithStore(store)
store.dispatch(loadTranslations(translationsObject))
store.dispatch(setLocale('es-AR'))
return { history, store }
}
_reducers.js_:
import { combineReducers } from 'redux'
import { persistReducer } from 'redux-persist'
import session from '../modules/sessions/session'
import { routerReducer } from 'react-router-redux'
import { i18nReducer } from 'react-redux-i18n'
import { reducer as toastrReducer } from 'react-redux-toastr'
import { reducer as formReducer } from 'redux-form/immutable'
import { persistConfig } from './createStore'
export const makeRootReducer = (asyncReducers) => {
return {
i18n: i18nReducer,
toastr: toastrReducer,
session,
router: routerReducer,
form: formReducer,
...asyncReducers
}
}
// This is needed if you use reducer code split (you don't put ALL your reducers in the makeRootReducer function...).
export const injectReducer = (store, { key, reducer }) => {
if (Object.hasOwnProperty.call(store.asyncReducers, key)) return
store.asyncReducers[key] = reducer
store.replaceReducer(persistReducer(persistConfig, combineReducers(makeRootReducer(store.asyncReducers))))
store.persistor.persist() // => **I think this is not needed anymore, i left it here when i was trying to make all this work together...**
}
Hope it helps you!
If anyone is interested - here is Dan Abramov's solution - though it's not specific to redux-persist:
you can use this:
import { persistStore } from 'redux-persist';and anywhere you want:
persistStore(this.props).purge();
I'm using this before my app is rendered for debugging purposes. If something gets messed up in my localStorage, I can reset it by visiting /?debug
if( window.location.search === '?debug' ){
persistor.purge();
}
render(
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<Router history={history}>
<App/>
</Router>
</PersistGate>
</Provider>,
document.getElementById('root')
);
@tommyalvarez could you provide an example showing how you're setting up everything?
Currently I'm facing the exact same issue you were having and I thought calling the
persistor.purge()method was an ok alternative.
from where did u import persistor and purge??
Most helpful comment
@landpy apologize for taking so long to get around to this. There are a few approaches here depending on your needs.
purgeStoredStateto purge state.import { purgeStoredState } from 'redux-persist'persistor.purge()in order to purge state. This is nice because it does not require config as an argument.