Redux-persist is not working: Page refresh clears the state - reactjs

To persist the state when the page is refreshed, I am trying to integrate redux-persist. However, it is not working. Page refresh clears the state. Here is how _persist object int the state looks:
_persist: {
version: -1,
rehydrated: true
}
Here is the configureStore.js:
import { createStore, applyMiddleware, compose } from "redux";
import logger from "redux-logger";
import thunk from "redux-thunk";
import rootReducer from "./_reducers/rootReducer";
import storage from "redux-persist/lib/storage";
import { persistStore, persistReducer } from "redux-persist";
const persistConfig = {
key: "root",
storage,
whitelist: []
};
const persistedReducer = persistReducer(persistConfig, rootReducer);
const middlewares = [thunk];
// if (__DEV__) react native check dev
middlewares.push(logger);
const store = createStore(
persistedReducer,
{},
compose(
applyMiddleware(...middlewares),
window.devToolsExtension ? window.devToolsExtension() : f => f)
);
const persistor = persistStore(store);
export { store, persistor };
And, here is the index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Router } from 'react-router-dom';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import { Provider } from 'react-redux';
import { PersistGate } from "redux-persist/lib/integration/react";
import { store, persistor } from "./configureStore";
const baseUrl = document.getElementsByTagName('base')[0].getAttribute('href');
const rootElement = document.getElementById('root');
ReactDOM.render(
<Router basename={baseUrl} history={history}>
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<App />
</PersistGate>
</Provider>
</Router>,
rootElement);
registerServiceWorker();
I cannot figure out the problem with the code. Any help?

const persistConfig = {
key: "root",
storage,
whitelist: ["pass reducer name which you want to persist in string"] e.g: whitelist: ["userAuth", "widgetAuth"]
};
if you want your whole state persist than remove whitelist key from persistConfig

For React Native Expo.
In My case this same issue happen after updating expo version.
Solution:
// import FSStorage from "redux-persist-expo-fs-storage";
import FSStorage from "redux-persist-fs-storage";
/*
Import change
*/
const primary = {
key: "root",
timeout: 0,
version: 1,
keyPrefix: "",
storage: FSStorage(),
stateReconciler: autoMergeLevel2, // see "Merge Process" section for details.
};
ADD keyPrefix: "", in config.
Hope this solutions work for others.

Related

Routing with react-router-dom, redux, apollo-client, connected-react-router and redux-persist

I am trying to configure an application and I am using: react class components, redux, react-redux, apollo-client, redux-persist and connected-react-redux and I am receiving the following error: "Uncaught TypeError: store.dispatch is not a function".
This is root reducer:
import { combineReducers } from "redux";
import { connectRouter } from "connected-react-router";
const createRootReducer = (history) => combineReducers({
rooter: connectRouter(history),
other reducers
})
export default createRootReducer
This is store.js:
import {createStore, applyMiddleware, compose} from 'redux'
import thunk from 'redux-thunk'
import createRootReducer from './Reducers'
import { persistStore, persistReducer } from 'redux-persist'
import storage from 'redux-persist/lib/storage'
import { createBrowserHistory } from 'history'
import { routerMiddleware } from 'connected-react-router'
const initialState = {}
export const history = createBrowserHistory()
const middware = [thunk]
const persistConfig = {
key: 'root',
storage,
}
const rootReducer = createRootReducer(history)
const persistedReducer = persistReducer(persistConfig, rootReducer)
const store = createStore(persistedReducer,
initialState,
compose(routerMiddleware(history),applyMiddleware(...middware))
)
const persistor = persistStore(store)
export {store, persistor}
And this is index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import {
ApolloClient,
InMemoryCache,
ApolloProvider,
} from "#apollo/client";
import { HashRouter } from 'react-router-dom';
import { Provider } from 'react-redux';
import {store, persistor, history} from './store';
import { PersistGate } from 'redux-persist/integration/react'
import { ConnectedRouter } from 'connected-react-router';
export const client = new ApolloClient({
uri: ' http://localhost:4000/',
cache: new InMemoryCache()
});
ReactDOM.render(
<React.StrictMode>
<ApolloProvider client={client}>
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<ConnectedRouter history={history}>
<App />
</ConnectedRouter>
</PersistGate></Provider >
</ApolloProvider>
</React.StrictMode>,
document.getElementById('root')
);
React-router-dom version: 5.3.0. React-router version : 5.2.1
Could you please help me?
The problem was with selector, because it is using some cache memory to memoize, and at first load, there was no cache memory. I found this post.
So I deleted the selector, and moved the function inside the reducer, for which was the selector.
Also I am not using "connected-react-router" anymore

React-persist is not persisting state

I am trying to implement redux-persist in my reactjs application, i am trying to persist user info but whenever i do refresh all the information is cleaned up and i am redirected to the login page.
store.js
import { createStore, applyMiddleware } from "redux";
import { composeWithDevTools } from "redux-devtools-extension";
import thunk from "redux-thunk";
import rootReducer from "./state/reducer";
import { persistStore, persistReducer } from "redux-persist";
import storage from "redux-persist/lib/storage";
const persistConfig = {
key: "primary",
storage,
whitelist: ["user", "artist"],
blacklist: ["alerts"],
};
const persistedReducer = persistReducer(persistConfig, rootReducer);
const middleWare = [thunk];
const initialState = {};
export const store = createStore(
persistedReducer,
initialState,
composeWithDevTools(applyMiddleware(...middleWare))
);
export const persistor = persistStore(store);
index.js for all reducers
import { combineReducers } from "redux";
import artistReducer from "./artistReducer";
import userReducer from "./userReducer";
import alertReducer from "./alertReducer";
export default combineReducers({
artist: artistReducer,
user: userReducer,
alerts: alertReducer,
});
App.js
import { persistor, store } from "./store";
import { PersistGate } from "redux-persist/integration/react";
function App() {
return (
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<div style={{ backgroundColor: "grey" }}>
<Router>
<Fragment>
<Navbar></Navbar>
<Alerts></Alerts>
<Switch> ...{ code continues }
Here i can see my data but on refresh it gets cleaned up
After hours of exploring internet i found this issue locked on github [ https://github.com/rt2zz/redux-persist/issues/826#fromHistory ] and there was much voted comment on it by hackrit which states
"Hi guys,
I found a solution to this problem. (might not apply to all the cases, but worked for me).
The problem was caused by my default return in my reducer, which I returned {...state}.
Once I changed the default return to just return state, everything work as expected." and this suggestion worked for me.
In My case this same issue happen after updating expo version.
Solution:
// import FSStorage from "redux-persist-expo-fs-storage";
import FSStorage from "redux-persist-fs-storage";
/*
Import change
*/
const primary = {
key: "root",
timeout: 0,
version: 1,
keyPrefix: "",
storage: FSStorage(),
stateReconciler: autoMergeLevel2, // see "Merge Process" section for details.
};
ADD keyPrefix: "", in config.
Hope this solutions work for others.

Implementing redux-persist

I'm trying to figure out how to configure redux persist in my application. I get a "'persistor' is not defined" in my react index.js file. I just need to persist a user_id so that when the page refreshes the data that is fetched on component did mount doesn't get lost.
this is my store.js file
import { createStore, combineReducers, applyMiddleware } from 'redux';
import userReducer from './reducers/userReducer';
import promiseMiddleware from 'redux-promise-middleware';
import { persistStore, persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
const rootReducer = combineReducers({
userReducer
});
const persistConfig = {
key: 'root',
storage,
}
const persistedReducer = persistReducer(persistConfig, rootReducer)
export default () => {
let store = createStore(persistedReducer, applyMiddleware(promiseMiddleware))
let persistor = persistStore(store)
return { store, persistor }
}
//export default createStore(rootReducer, applyMiddleware(promiseMiddleware));
and this is my index.js file in my react app.
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { HashRouter as Router } from 'react-router-dom';
import { Provider } from 'react-redux';
import store from './redux/store';
import { PersistGate } from 'redux-persist/integration/react'
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<Router>
<App />
</Router>
</PersistGate>
</Provider>
</React.StrictMode>,
document.getElementById('root')
);
reportWebVitals();
The store you're importing is a function that should be fired to get the actual store along with the persistor.
Refactor your store import to look like this
import useStore from './redux/store';
const { store, persistor } = useStore();
OR:
Refactor your store.js file
let store = createStore(persistedReducer, applyMiddleware(promiseMiddleware));
let persistor = persistStore(store);
export { store, persistor }
And import it from your index.js file like this
import { store, persistor } from './redux/store';

Why is Redux-Persist not persisting the store

Hi there everyone I was messing around with react(redux to be precise) and came across a problem. When I refresh the page redux store does as well everything returns to its initial value, I googled the problem and found out that I have to use redux-persist. However even that is not working, I think the problem is with how I configured redux-persist but I could be wrong.
The code below is how I went about the redux-persist configuration.
// configureStore.js
import { createStore, applyMiddleware } from "redux";
import { persistStore, persistReducer } from "redux-persist";
import storage from "redux-persist/lib/storage";
import rootReducer from "../reducers/index";
import { composeWithDevTools } from "redux-devtools-extension";
import thunk from "redux-thunk";
const persistConfig = {
key: "root",
storage,
};
const persistedReducer = persistReducer(persistConfig, rootReducer);
export const store = createStore(
persistedReducer,
composeWithDevTools(applyMiddleware(thunk))
);
export const persistedStore = persistStore(store);
The code below shows how I went about making the rootReducer.
// index.js
import { combineReducers } from "redux";
import { reducer as formReducer } from "redux-form";
import authReducer from "./auth";
import messageReducer from "./message";
import chatroomReducer from "./chatroom";
import { LOGOUT_SUCCESS } from "../actions/authTypes";
const apiReducer = combineReducers({
authReducer,
messageReducer,
chatroomReducer,
form: formReducer,
});
const rootReducer = (state, action) => {
if (action.type === LOGOUT_SUCCESS) {
state = undefined;
}
return apiReducer(state, action);
};
export default rootReducer;
And the code below is the index.js that comes when creating the react app.
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { PersistGate } from "redux-persist/integration/react";
import { Provider } from "react-redux";
import { store, persistedStore } from "./Redux/configureStore";
ReactDOM.render(
<Provider store={store}>
<PersistGate loading={null} persistor={persistedStore}>
<React.StrictMode>
<App />
</React.StrictMode>
</PersistGate>
</Provider>,
document.getElementById("root")
);
reportWebVitals();
Can anyone tell me what is wrong with my code? If you need additional info please let me know.
Try configuring the whitelist, where you must indicate which reducers to store.
Remember to import the reducers before adding them to the list
import navigation from "./reducers/navigation";
// WHITELIST
const persistConfig = {
key: 'root',
storage: storage,
whitelist: ['navigation'] // only navigation will be persisted
};
First, you need to import storage from Async
import AsyncStorage from '#react-native-community/async-storage';
Use WhiteList like this
const persistConfig = {
key: 'root',
storage: AsyncStorage,
whitelist: [
'user'
],
};
"user" is the specific root reducer you want to store
As per this answer, you also need to clear out the redux-persist storage when you catch the LOGOUT_SUCCESS action.
First, you need to import the appropriate storage engine and then clear it out completely.
const rootReducer = (state, action) => {
if (action.type === SIGNOUT_REQUEST) {
// for all keys defined in your persistConfig(s)
storage.removeItem('persist:root')
// storage.removeItem('persist:otherKey')
return appReducer(undefined, action);
}
return appReducer(state, action);
};

How to persist redux store to local storage rather than async storage in react native

I am using redux-persist to persist state of my app. By default it persist state inside AsyncStorage but I want it to be in localStorage. There is nothing about this in official docs as far as react-native is concerned.
This is my code till now:
import { persistStore, persistCombineReducers } from 'redux-persist';
import storage from 'redux-persist/es/storage';
const config = {
key: 'root',
storage,
debug: true
}
export const ConfigureStore = () => {
const store = createStore(
persistCombineReducers(config,{
dishes,
comments,
promotions,
leaders,
favorite
}),
applyMiddleware(thunk)
);
const persistor = persistStore(store)
return {persistor, store};
}
Can I do something like this:
import storage from 'redux-persist/es/localStorage';
...
storage: storage
Please help me on the topic if anyone has ever used it before. Thank You!
One thing i noticed is that you import says
import storage from 'redux-persist/es/storage';
But in the documentation is used
import storage from 'redux-persist/lib/storage'
Otherwise you can use this approach like in the documentation.
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 }
}
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>
);
};

Resources