Implementing redux-persist - reactjs

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';

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

Getting an Error: Before running a Saga, you must mount the Saga middleware on the Store using the applyMiddleware

I'm getting the error on the header when I try to add the store into my app
this is my store.js code
import { createStore, applyMiddleware } from 'redux';
import { persistStore } from 'redux-persist';
import logger from 'redux-logger';
import createSagaMiddleware from 'redux-saga';
import { composeWithDevTools } from 'redux-devtools-extension';
import rootReducer from './root-reducer';
import rootSaga from './root-saga';
const sagaMiddleware = createSagaMiddleware();
const middlewares = [sagaMiddleware];
//if (process.env.NODE_ENV === 'development') {
middlewares.push(logger);
//}
sagaMiddleware.run(rootSaga);
const configureStore = () => {
const store = createStore(rootReducer, composeWithDevTools(applyMiddleware(...middlewares)));
const persistor = persistStore(store);
return { persistor, store };
};
export default configureStore;
This is my index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router } from "react-router-dom";
import { Provider } from 'react-redux';
import { PersistGate } from 'redux-persist/integration/react';
import App from './App';
import configureStore from './redux/store';
ReactDOM.render(
<React.StrictMode>
<Provider store={configureStore}>
<Router>
<PersistGate persistor={configureStore}>
<App />
</PersistGate>
</Router>
</Provider>
</React.StrictMode>,
document.getElementById('root')
);
Could you please help identify the issue here please? Thanks in advance
Running saga should be after creating the store like that:
...
const configureStore = () => {
const store = createStore(rootReducer, composeWithDevTools(applyMiddleware(...middlewares)));
sagaMiddleware.run(rootSaga);
const persistor = persistStore(store);
return { persistor, store };
};
Another point here, regarding TypeError: store.getState is not a function: you're returning function, not a result of the function: so typically it should be like this:
const configureStore = () => {
const store = createStore(
rootReducer,
composeWithDevTools(applyMiddleware(...middlewares))
);
const persistor = persistStore(store);
sagaMiddleware.run(rootSaga);
return { persistor, store };
};
export default configureStore();
The persistor isn't returned here, but the application works.
There is an instruction how to add redux-persist https://github.com/rt2zz/redux-persist#basic-usage, but then you need to get separately store and persistor like:
import configureStore from "./store";
ReactDOM.render(
<React.StrictMode>
<Provider store={configureStore.store}>
<Router>
<App />
</Router>
</Provider>
</React.StrictMode>,
document.getElementById("root")
);```
Getting an Error: Before running a Saga, you must mount the Saga middleware on the Store using the applyMiddleware
Error explanation
Your error says you are trying to execute a saga too soon
Explaining you to run your middleware before.
Therefore your solution is to execute `saggaMiddleware.run() after creating your store.
What happened based on your code
You were trying to execute sagaMiddleware.run() method before mounting your store at the third line with composeWithDevTools(applyMiddleware(...middlewares))
Solution
Here is a solution respecting your line declarations order + added one more line before return to execute the runSagaMiddleware
const runSagaMiddleware = () => sagaMiddleware.run(rootSaga);
const configureStore = () => {
const store = createStore(rootReducer, composeWithDevTools(applyMiddleware(...middlewares)));
const persistor = persistStore(store);
runSagaMiddleware();
return { persistor, store };
};

React- How to make states persists after page refresh?

I made a single page application using React.js with a login page and perfil page. All works well but recently I noticed when refresh my page, all states are empty. Please someone can say me how to fix that issue, I mean what library import and where add it
my index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './components/App.jsx';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(<App />, document.getElementById('root'));
serviceWorker.unregister();
this is my App.jsx
import React from 'react';
import '../App.css';
import AppRoutes from './AppRoutes';
import { Provider } from "react-redux";
import store from '../redux/store'
store.dispatch(getTallerList())
const App = () => (
<Provider store={store}>
<AppRoutes />
</Provider> )
export default App;
and my store.js
import { applyMiddleware, combineReducers, createStore } from 'redux'
import { ADD_TO_CART, GET_COURSE_LIST, USUARIO_LOGIN } from './action'
import { composeWithDevTools } from 'redux-devtools-extension'
import { persistStore, persistReducer } from 'redux-persist'
import thunk from 'redux-thunk'
const initialCart = {
cart:[]
}
const initialCourses ={
courses:[]
}
const initialUser ={
user:{}
}
const cartReducer = ( state = initialCart,action) => {
if(action.type===ADD_TO_CART)
{
if(state.cart.find(c=>c===action.id))
{
return state
}
return{
...state,
cart: state.cart.concat(action.id),
}
}
return state
}
const coursesReducer = (state=initialCourses, action) =>{
console.log(action)
if(action.type === GET_COURSE_LIST){
return {
...state,
courses: action.courses
}
}
return state
}
const userReducer = (state=initialUser, action)=>{
console.log(action)
if(action.type === USER_LOGIN){
return {
...state,
user: action.user
}
}
return state
}
export default createStore(combineReducers({cartReducer, coursesReducer, userReducer}), composeWithDevTools(applyMiddleware(thunk)))
Try to store value in local storage and at the time of page load get value from local storage. If you have some more values you should use redux for data storage.
It's not an issue, it's the way it works. When you refresh the entire app builds once again from the scratch.
But to persist the store upon refresh you can use these redux middlewares -
redux-persist or
redux-storage
Use this configuration as you are using redux-persist. This is my configuration, just change the main app, reducers, and actions according to your need.
import React from 'react';
import ReactDOM from 'react-dom';
import MyApp from './MyApp';
import {Provider} from 'react-redux';
import {applyMiddleware, createStore} from "redux";
import allReducers from './reducers/index';
import {persistReducer, persistStore} from 'redux-persist';
import {PersistGate} from 'redux-persist/integration/react';
import storage from 'redux-persist/lib/storage';
import thunk from "redux-thunk";
const persistConfig = {
key: 'root',
storage,
};
const persistedReducer = persistReducer(persistConfig, allReducers);
let store = createStore(persistedReducer, applyMiddleware(thunk));
let persistor = persistStore(store);
ReactDOM.render(<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<MyApp/>
</PersistGate>
</Provider>, document.getElementById('root'));
Updated : you can do like this
import {combineReducers} from "redux";
import Users from './load-user';
const allReducers = combineReducers({
users: Users,
})
export default allReducers

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

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.

react native app stay blank after implementing redux-persist?

Everyone
i am trying to persist my store using redux-persist but after implementing it to my app.js, i get white screen, i looked for this error, and the only thing i could find was to purge the persistor in componentDidMount() and even that didn't work for me:
App.js:
import React from 'react';
import { AppLoading, Asset, Font } from 'expo';
import { PersistGate } from 'redux-persist/integration/react';
import { Ionicons } from '#expo/vector-icons';
import { Provider } from 'react-redux';
import storeConfig from './config/store';
import RootNavigation from './navigation/RootNavigation';
import Splash from './screens/Splash'
const {persistor, store} = storeConfig();
// normal code
render() {
if (!this.state.isLoadingComplete ) {
return (
<AppLoading
startAsync={this._loadResourcesAsync}
onError={this._handleLoadingError}
onFinish={this._handleFinishLoading}
/>
);
} else {
return (
<Provider store={store}>
<PersistGate loading={<Splash /> } persistor={persistor}>
<RootNavigation />
</PersistGate>
</Provider>
);
}
}
store.js :
import { createStore } from 'redux';
import { persistStore, persistReducer } from 'redux-persist'
import storage from 'redux-persist/lib/storage'
import logger from 'redux-logger';
import reducers from '../reducers';
const persistConfig = {
key: 'root',
storage,
};
const pReducer = persistReducer(persistConfig, reducers);
export const store = createStore(pReducer);
export const persistor = persistStore(store);

Resources