React- How to make states persists after page refresh? - reactjs

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

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

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);
};

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

React-router-redux push action is not working

I am trying to navigate to Main page once authentication is successful, I am using redux-saga for making API calls. Below is my login generator function:
import * as Type from '../actions/types';
import { takeLatest, put, call } from 'redux-saga/effects';
import firebase from 'firebase';
import { push } from 'react-router-redux';
function* loginUser(action) {
const auth = firebase.auth();
try{
console.log(action.user);
const result = yield call([auth, auth.signInWithEmailAndPassword], action.user.email, action.user.password);
console.log('login sucess');
yield put({type: Type.AUTH_SUCCESSFULL, user: action.user, authMessage:'Login Success'});
console.log('done'); //being logged
yield put(push('/home')); /not being redirected to home. Even the browser url is not changing
console.log('pushed'); //being logged
}
catch(error){
console.log(error.message);
yield put({type: Type.AUTH_FAILED, errorMessage: error.message});
}
}
I just installed react-router-redux and tried doing this, Can someone please tell me what I am doing wrong?
I faced the same issue and following is my solution. Code you have added has not an issue. You need do some extra works to make this work.
Reducer.js
import { combineReducers } from 'redux';
import { connectRouter } from 'connected-react-router';
import { History } from 'history'
const redusers = {
...
}
const mainReducer = (history: History) => combineReducers({
router: connectRouter(history),
...redusers
})
export default mainReducer;
Store.js
import { createStore, applyMiddleware } from 'redux';
import createSagaMiddleware from 'redux-saga';
import logger from 'redux-logger';
import { createBrowserHistory } from 'history'
import { routerMiddleware } from 'connected-react-router'
import mainReducer from './mainReducer';
import rootSaga from './rootSaga';
export const history = createBrowserHistory()
const configureStore = (preloadedState?: any) => {
const sagaMiddleware = createSagaMiddleware();
const store = createStore(
mainReducer(history),
preloadedState,
applyMiddleware(routerMiddleware(history), logger, sagaMiddleware),
);
sagaMiddleware.run(rootSaga);
return store;
};
export default configureStore;
index.js
import React, { Suspense } from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import App from './App';
import * as serviceWorker from './serviceWorker';
import configureStore, { history } from './store';
const store = configureStore();
const app = (
<Provider store={store}>
<App history={history} />
</Provider>
);
App.js - only added necessary code lines bellow
...
import { History } from 'history'
import { ConnectedRouter } from 'connected-react-router'
...
const {history} = props;
...
return(){
...
<ConnectedRouter history={history}>
{routes}
</ConnectedRouter>
...
}
After setting up above things on your app, it will work as you want.
The other thing is we are no longer using BrowserHistory in the app because custom history has implemented.

Resources