I want to keep my state data as it is even after browser refresh. For that i'm using Redux Persist (https://www.npmjs.com/package/redux-persist#basic-usage) library. When implementing this library i'm getting undefined for the current states in the reducers. For ex:
TypeError: Cannot read property 'modalType' of undefined
What am i doing wrong in the following code
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
//import * as serviceWorker from './serviceWorker';
import { createStore, applyMiddleware } from 'redux';
import { Provider } from 'react-redux';
import { composeWithDevTools } from 'redux-devtools-extension';
import thunk from 'redux-thunk';
import { routerMiddleware } from 'react-router-redux';
import ReducerStore from './reducers/rootReducer.js';
import '../node_modules/bootstrap/dist/css/bootstrap.min.css';
import { Router } from 'react-router-dom';
import history from './history';
import { persistStore, persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
const persistConfig = {
key: 'root',
storage,
}
const persistedReducer = persistReducer(persistConfig, ReducerStore)
const middleware = routerMiddleware('');
const store = createStore(persistedReducer, composeWithDevTools(
applyMiddleware(middleware, thunk),
))
const persistor = persistStore(store);
ReactDOM.render(<Provider store={persistor}><Router history={history}><App /></Router></Provider>, document.getElementById('root'));
I was missing PersistGate. Once adding it i was able to make it work
import {PersistGate} from 'redux-persist/integration/react'
and then
ReactDOM.render(<Provider store={store}><PersistGate loading={null} persistor={persistor}><Router history={history}><App /></Router></PersistGate></Provider>, document.getElementById('root'));
Related
I stuck with this error:
Uncaught Error: Expected the root reducer to be a function. Instead, received:''
I've tried every answer I could find but none of them worked, I hope you guys can help me
My rootReducer
import {combineReducers} from 'redux'
import changeCategoryReducer from './changeCategoryReducer'
import categoryListReducer from './categoryListReducer'
import productListReducer from './productListReducer'
import cartReducer from './cartReducer'
import saveProductReducer from './saveProductReducer'
const rootReducer = combineReducers({
changeCategoryReducer,
categoryListReducer,
productListReducer,
cartReducer,
saveProductReducer
});
export default rootReducer;
configure Store
import {createStore, applyMiddleware} from 'redux'
import * as rootReducer from './index.js'
import thunk from 'redux-thunk'
export default function configureStore(){
return createStore(rootReducer, applyMiddleware(thunk))
}
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './components/root/App';
import reportWebVitals from './reportWebVitals';
import 'bootstrap/dist/css/bootstrap.min.css';
import { Provider } from 'react-redux'
import configureStore from './redux/reducers/configureStore'
import 'alertifyjs/build/css/alertify.min.css'
import { BrowserRouter } from 'react-router-dom'
const store = configureStore();
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<BrowserRouter>
<Provider store={store}>
<App />
</Provider>
</BrowserRouter>
</React.StrictMode>
);
reportWebVitals();
You're not correctly importing your rootReducer in the store creation.
Instead of importing *, you should import the default export:
import {createStore, applyMiddleware} from 'redux'
import rootReducer from './index.js' // <-- change here
import thunk from 'redux-thunk'
export default function configureStore(){
return createStore(rootReducer, applyMiddleware(thunk))
}
using import * as rootReducer from './index.js' means you end up with an object like:
rootReducer: {
default: createReducer(...)
}
createStore is #deprecated so im trying to replace with configurationStore, i think the post data from my cluster is not showing because of that
```
import React from 'react';
import ReactDom from 'react-dom/client';
import { Provider } from 'react-redux';
import {createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import reducers from "./reducers";
import App from './App'
const store = createStore(reducers, (compose(applyMiddleware(thunk))))
const root = ReactDom.createRoot(document.getElementById("root"));
root.render(
<Provider store={store}>
<App />
</Provider>
);
And im trying to do it like this:
import React from 'react';
import ReactDom from 'react-dom/client';
import { Provider } from 'react-redux';
import { applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import { configureStore } from '#reduxjs/toolkit'
import reducers from "./reducers";
import App from './App'
const store = configureStore(reducers, (compose(applyMiddleware(thunk))))
const root = ReactDom.createRoot(document.getElementById("root"));
root.render(
<Provider store={store}>
<App />
</Provider>
);
```
Of Course it didn't work i'm trying to figure out how it could be
You would do
const store = configureStore({ reducer: reducers })
The thunk middleware is active automatically. compose and applyMiddleware are not needed any more. So is combineReducers.
If you had
const reducers = combineReducers({
a: reducerA,
b: reducerB
})
you could also just instead do
const store = configureStore({
reducer: {
a: reducerA,
b: reducerB
}
})
If you were still using createStore, that means that you were generally using an outdated style of Redux that is about 4x times the code of modern Redux.
Modern Redux does not use switch..case reducer, ACTION_TYPE constants, immutable reducer logic, hand-written action creators or connect & mapStateToProps. You might have been misled by an outdated tutorial.
I would highly recommend you to follow the official Redux tutorial which will leave you with knowledge of modern Redux and in the end much cleaner and easy to maintain code.
I have added redux-persist in my code and it isn't persisting the state, instead I am always getting the initial state.
Here's the code of my root-reducer
import { combineReducers } from "redux";
import { persistReducer } from "redux-persist";
import storage from "redux-persist/lib/storage";
import userReducer from "./Users/user-reducer";
import cartReducer from "./Cart/cart-reducer";
const persistConfig = {
key: "root",
storage,
whitelist: ["cart"],
};
const rootReducer = combineReducers({
user: userReducer,
cart: cartReducer,
});
export default persistReducer(persistConfig, rootReducer);
and this is my store.js file
import { createStore, applyMiddleware } from "redux";
import logger from "redux-logger";
import rootReducer from "./root-reducer";
import { persistStore } from "redux-persist";
const middlewares = [logger];
export const store = createStore(rootReducer, applyMiddleware(...middlewares));
export const persistor = persistStore(store);
Here's my index.js file
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import { BrowserRouter } from "react-router-dom";
import { Provider } from "react-redux";
import { store, persistor } from "./redux/Store";
import { PersistGate } from "redux-persist/integration/react";
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<BrowserRouter>
<PersistGate persistor={persistor}>
<App />
</PersistGate>
</BrowserRouter>
</Provider>
</React.StrictMode>,
document.getElementById("root")
);
Whenever I am refreshing my page with the initial state, I am getting rehydrated: true but after firing some action I am getting rehydrated: false.
Check your reducer.js and make sure the bottom of the reducer in the file is
default:
return state;
and not
default:
return {
...state,
};```
I am trying to add persistence to my redux stores, I am using Immutable.js within my webapp. I have seen the following libraries: https://github.com/rt2zz/redux-persist and https://github.com/rt2zz/redux-persist-immutable I am wondering exactly how to create the persister and the store in context of my application, please see the following config-store.js:
import rootReducer from '../reducers'
import {
createStore,
compose,
applyMiddleware
} from 'redux'
import thunk from 'redux-thunk'
export default (initialState) => {
return createStore(
rootReducer,
initialState,
compose(
applyMiddleware(thunk),
window.devToolsExtension ? window.devToolsExtension() : f => f
)
);
};
and my index.js:
import React from 'react';
import {render} from 'react-dom';
import './index.css';
import App from './App';
import {Provider} from 'react-redux';
import configureStore from './store/configure-store';
import registerServiceWorker from './registerServiceWorker';
const store = configureStore();
render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)
registerServiceWorker();
Load the persiting state from local storage.
if (localStorage.getItem("state")) {
var serializedState = localStorage.getItem("state");
/* upload changes to server here */
preloadedState = JSON.parse(serializedState);
}
Save store changes to local storage.
store.subscribe(() => {
var serializedState = JSON.stringify(store.getState());
localStorage.setItem("state", serializedState);
});
I am getting the following error on my react-redux & redux-persist setup:
The above error occurred in the component: in Connect(App) (created by
Route) in Route (created by withRouter(Connect(App))) in
withRouter(Connect(App)) in Router (created by BrowserRouter) in
BrowserRouter in PersistGate in Provider
I have it setup like this:
store.js
import {applyMiddleware, createStore} from 'redux';
import {persistStore,persistCombineReducers} from 'redux-persist';
import storage from 'redux-persist/es/storage' // default: localStorage if web, AsyncStorage if react-native
import { logger } from 'redux-logger';
import thunk from 'redux-thunk';
import promise from 'redux-promise-middleware';
import reducer from './reducers'
const middleware = applyMiddleware(promise(), thunk, logger);
const config = {
key: 'root',
storage,
};
const reducers = persistCombineReducers(config, {reducer});
export const configureStore = () => {
const store = createStore(reducers, middleware);
const persistor = persistStore(store);
return { persistor, store };
};
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import {BrowserRouter} from 'react-router-dom';
import {Provider} from 'react-redux';
import Bootstrap from 'bootstrap/dist/css/bootstrap.css';
import './css/app.css';
import App from './containers/App';
import { PersistGate } from 'redux-persist/es/integration/react'
import configureStore from './store';
const { persistor, store } = configureStore()
ReactDOM.render(
<Provider store={store} >
<PersistGate persistor={persistor}>
<BrowserRouter>
<App/>
</BrowserRouter>
</PersistGate>
</Provider>,
document.getElementById('root')
);
App.js
import React from 'react'
import { withRouter, Switch, Route } from 'react-router-dom'
import { connect } from 'react-redux'
...
#withRouter
#connect((store) => {
return {
isAuthenticated: store.auth.isAuthenticated,
};
})
export default class App extends React.Component {
render() {
...
}
}
UPDATE 1
Full console log
UPDATE 2
Is this the right way to declare the reducer? It works fine without redux-persist
authReducer.js
export default function reducer(state = {
isAuthenticated: false
}, action) {
...
}
UPDATE 3
REHYDRATE console log
UPDATE 4
index.js (in reducers folder)
import { combineReducers } from 'redux';
import user from './userReducer';
import auth from './authReducer';
export default combineReducers({
user,
auth
})
So the problem was that one should not use both combineReducers and persistCombineReducers in one go. Similar situation could be found here https://github.com/rt2zz/redux-persist/issues/516