I am trying to persist my immutable states in localStorage. Below is my reducer index.js
import { combineReducers } from 'redux';
import posts from './PostReducer';
import polls from './PollReducer';
import categories from './CategoryReducer';
import activeThreads from './ActiveThreadReducer';
export default combineReducers({
posts,
polls,
categories,
activeThreads
})
In my persistStore.js, i have something like below.
import immutableTransform from 'redux-persist-transform-immutable'
import { persistStore, autoRehydrate } from 'redux-persist-immutable';
import { persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
const config = {
key: 'root',
storage,
};
const loggerMiddleware = createLogger();
const finalCreateStore =
composeWithDevTools(
applyMiddleware(
thunkMiddleware,
loggerMiddleware,
),
autoRehydrate()
);
const reducer = persistReducer(config, reducers)
export const store = createStore(reducer, undefined, finalCreateStore);
export const persistor = persistStore(store, { transforms: [immutableTransform({})] }, () => {
console.log('rehydration complete', store.getState());
return store;
});
and in my main APP,
return (
<Provider store={store}>
<PersistGate
loading={<Loading />}
onBeforeLift={this.onBeforeLift}
persistor={persistor}>
<Router history={browserHistory}
createElement={this.createElementWithActions}>
<Route path="/" component={Main}>
...
</Router>
</PersistGate>
</Provider>
);
My app is returning the error below.
Uncaught TypeError: persistor.getState is not a function
at PersistGate._this.handlePersistorState (react.js:41)
at PersistGate.componentDidMount (react.js:55)
at ReactCompositeComponent.js:262
at measureLifeCyclePerf (ReactCompositeComponent.js:73)
at ReactCompositeComponent.js:261
at CallbackQueue.notifyAll (CallbackQueue.js:74)
at ReactReconcileTransaction.close (ReactReconcileTransaction.js:78)
at ReactReconcileTransaction.closeAll (Transaction.js:207)
at ReactReconcileTransaction.perform (Transaction.js:154)
at batchedMountComponentIntoNode (ReactMount.js:124)
I read the documentation on redux-persist here and Here. Please what am i doing wrong and what does the error implies ?Anyhelp would be appreciated
Related
I have been setting up redux on my next.js application but I am continuously getting this error. I'm not able to detect from where it's coming and for what reason. I'm using next.js 13 version and app directory is not enabled. Here is below screenshot and code which I wrote in order to add redux in my application.
_app.tsx
import "../styles/globals.css";
import type { AppProps } from "next/app";
import Layout from "components/Layout/Layout";
import { Provider } from "react-redux";
// import { PersistGate } from "redux-persist/integration/react";
import store from "store/store";
import React from "react";
export default function App({ Component, pageProps }: AppProps) {
return (
<Provider store={store}>
{/* <PersistGate loading={<>Loading...</>} persistor={persistor}> */}
<Layout>
<Component {...pageProps} />
</Layout>
{/* </PersistGate> */}
</Provider>
);
}
store.ts
import { configureStore } from "#reduxjs/toolkit";
import rootReducer from "reducers/root-reducer";
// import rootReducer from "reducers/root-reducer";
// import { persistStore, persistReducer } from "redux-persist";
// import storage from "redux-persist/lib/storage";
// import React from "react";
// const persistConfig = { key: "root", storage };
// const persistedReducer = persistReducer(persistConfig, rootReducer);
const store = configureStore({
reducer: rootReducer,
});
export default store;
// export const persistor = persistStore(store);
The commented code you see is what I made in order to check if the error gets out but its still there. What is the issue?
Im adding Redux persist into my applcaition for local storage. I believe ive followed the implementation correctly and i keep getting the error:
Cannot read property 'subscribe' of undefined TypeError: PersistGate.componentDidMount
node_modules/redux-persist/es/integration/react.js:76
Here is my code.
store.js
import { createStore, applyMiddleware } from 'redux';
import { persistStore } from 'redux-persist';
import logger from 'redux-logger';
import rootReducer from './root.reducer';
const middlewares = [logger];
export const store = createStore(rootReducer, applyMiddleware(...middlewares));
export const persistor = persistStore(store);
export default { store, persistor };
root.reducer.js
import { combineReducers } from 'redux';
import { persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import userReducer from './user/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);
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import {BrowserRouter} from 'react-router-dom';
import App from './App';
import { Provider } from 'react-redux';
import { PersistGate } from 'redux-persist/integration/react';
import Store from './redux/store';
ReactDOM.render(
<Provider store={Store.store}>
<BrowserRouter>
<PersistGate persistor={Store.persistor} />
<App />
<PersistGate/>
</BrowserRouter>
</Provider>,
document.getElementById('root')
);
Syntax was off in index.js PersisGate wrapper.
Correct syntax is
<PersistGate persistor={Store.persistor}>
<App />
</PersistGate>
you messing something which is:
import {store,persistor} from "./redux/store";
<Provider store = {store} >
<Router >
<PersistGate loading = {null} persistor = {persistor}>
<App />
</PersistGate>
</Router>
</Provider>
i hope this solution help somone
I'm currently using redux-persist to persistent data storage in my react-redux application. I have set it up according to the documentation. I have tested it on a separate project with npx create-react-app. The persistent storage was working properly.
When I integrate it in my actual working project, the state saving doesn't work. Can someone help me with this?
Here is my store.js:
import { createStore, applyMiddleware, compose } from 'redux';
import { routerMiddleware } from 'react-router-redux';
import thunk from 'redux-thunk';
import rootReducers from './reducers';
// imports for persistance redux state
import { persistStore, persistReducer } from 'redux-persist'
import storage from 'redux-persist/lib/storage' // defaults to localStorage for web
const middleware = [thunk, routerMiddleware(history)];
const initialState = {};
//config for redux-persist
const persistConfig = {
key: 'root',
storage,
}
const persistedReducer = persistReducer(persistConfig, rootReducers)
function composeWithApplyMiddlewares() {
if (window.__REDUX_DEVTOOLS_EXTENSION__) {
return compose(applyMiddleware(...middleware), window.__REDUX_DEVTOOLS_EXTENSION__());
}
return compose(applyMiddleware(...middleware));
}
const createMyStore = () =>
createStore(
persistedReducer,
initialState,
composeWithApplyMiddlewares(),
);
let persistor = persistStore(createMyStore());
export default createMyStore();
index.js:
import React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import { syncHistoryWithStore } from 'react-router-redux';
import { Router, Route, browserHistory } from 'react-router';
import RandomID from 'random-id';
import 'normalize.css/normalize.css';
import 'plottable/plottable.css';
import store from './store';
import SignInContainer from './containers/Auth/Signin';
import SignUpContainer from './containers/Auth/Signup';
import ForgotPasswordContainer from './containers/Auth/ForgotPassword';
import ResetPasswordContainer from './containers/Auth/ResetPassword';
import CompleteSignupContainer from './containers/Auth/CompleteSignup';
import UsersListContainer from './containers/Users/List';
import CreateEndpointContainer from './containers/Endpoints/CreateEndpoint';
import TestMessagesContainer from './containers/TestMessages';
import Dashboard from './containers/Dashboard';
import initialize from './actions/initialize';
import Setting from './containers/Setting/Main';
const root = document.getElementById('root');
const history = syncHistoryWithStore(browserHistory, store);
const rand = RandomID(16, 'A0');
localStorage.setItem('authStateKey', rand);
const reduxOauthConfig = {
backend: {
apiUrl: 'http://0.0.0.0:4000', // TODO: Change backend URL here
signOutPath: null, // Add signout path to destroy session token
tokenValidationPath: '/svr/ping',
authProviderPaths: {
facebook: '/svr/auth/facebook',
github: '/svr/auth/github',
gitlab: '/svr/auth/gitlab',
google: '/svr/auth/google',
twitter: '/svr/auth/twitter',
},
},
};
const requireAuth = (nextState, replace) => {
const state = store.getState();
const isSignedIn = state.auth.authUser.isSignedIn;
// const isSignupCompleted = state.auth.authUser.isSignupCompleted;
// Complete signup first before user can do anything
// if (!isSignupCompleted && nextState.location.pathname !== '/complete-signup') {
// replace({
// pathname: '/complete-signup',
// state: { nextPathname: nextState.location.pathname },
// });
// }
if (!isSignedIn) {
replace({
pathname: '/signin',
state: { nextPathname: nextState.location.pathname },
});
}
};
const publicOnly = (nextState, replace) => {
const state = store.getState();
const isSignedIn = state.auth.authUser.isSignedIn;
if (isSignedIn) {
replace({
pathname: '/',
state: { nextPathname: nextState.location.pathname },
});
}
};
store.dispatch(initialize(reduxOauthConfig)).then(
() => {
render(
<Provider store={store}>
<Router history={history}>
<Route exact path="/signup" component={SignUpContainer} onEnter={publicOnly} />
<Route exact path="/signin" component={SignInContainer} onEnter={publicOnly} />
<Route exact path="/forgot-password" component={ForgotPasswordContainer} onEnter={publicOnly} />
<Route exact path="/reset-password" component={ResetPasswordContainer} onEnter={publicOnly} />
<Route exact path="/complete-signup" component={CompleteSignupContainer} onEnter={requireAuth} />
<Route exact path="/users" component={UsersListContainer} onEnter={requireAuth} />
<Route exact path="/chat" component={TestMessagesContainer} onEnter={requireAuth} />
<Route exact path="/add-endpoint" component={CreateEndpointContainer} onEnter={requireAuth} />
<Route exact path="/" component={Dashboard} onEnter={requireAuth} />
<Route exact path="/:userId/setting" component={Setting} onEnter={publicOnly} />
</Router>
</Provider>
, root,
);
},
);
reducers/index.js:
import { combineReducers } from 'redux';
import { routerReducer } from 'react-router-redux';
import message from './message';
import users from './users';
import endpoints from './endpoints';
import toasts from './toasts';
import auth from './auth';
export default combineReducers({
routing: routerReducer,
users,
endpoints,
ui: toasts,
chat: message,
auth,
});
Thanks for your attention.
I just started to use Redux Persist, and for some reason I can't get it to work.
(Cannot read property 'subscribe' of undefined error)
Persistor.js
import { createStore } from 'redux'
import { persistStore, persistReducer } from 'redux-persist'
import store from 'redux-persist/es/storage/session' // defaults to
localStorage for web and AsyncStorage for react-native
import rootReducer from './reducers'
const persistConfig = {
key: 'root',
storage: store,
}
const persistedReducer = persistReducer(persistConfig, rootReducer)
export default () => {
let store = createStore(persistedReducer)
let persistor = persistStore(store)
return { store: store, persistor: persistor }
}
index.js
import React from 'react';
import App from './components/App/App';
// import registerServiceWorker from './registerServiceWorker';
import { render } from 'react-dom'
import { createStore } from 'redux'
import { Provider } from 'react-redux'
import { PersistGate } from 'redux-persist/integration/react'
import persistor from './Persistor'
import rootReducer from './reducers'
import 'bootstrap/dist/css/bootstrap.min.css'
import './index.css'
render(
<Provider store={persistor.persistor}>
<PersistGate loading={null} persistor={persistor.store}>
<App />
</PersistGate>
</Provider>,
document.getElementById('root')
)
with normal Redux its worked properly. But as soon I tried to switch Persist Redux I got the error I write above.
The persistor value you are importing in index isn’t an object. It is a function that returns an object containing store and the persistor.
Instantiate the persistor function and then also swap your values assigned to store in Provider with persistor in persistgate.
Rename your import to something like configureStore to prevent any conflict.
const { store, persistor } = configureStore()
render(
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<App />
</PersistGate>
</Provider>,
document.getElementById('root')
)
I'm managing my React application route with react-router and react-router-redux.
I setting router with following configuration:
import {Provider} from 'react-redux'
import {Router, browserHistory} from 'react-router'
import {createStore, combineReducers} from 'redux'
import {routerReducer} from 'react-router-redux';
import {syncHistoryWithStore} from 'react-router-redux'
import Reducers from './reducers'; // contains all my reducers,
const store = createStore(combineReducers(
{...Reducers, routerReducer}
));
const history = syncHistoryWithStore(browserHistory, store);
const AppRoute = (
<Provider store={store}>
<Router history={history}>
<Route path='login' components={PageLogin}/>
<Route path='system' components={PageSystem}>
<Route path="profile" component={PageProfile}/>
</Route>
</Router>
</Provider>
);
export default AppRoute;
When I try dispatch any router function:
import React from 'react';
import {Link, Route} from 'react-router';
import {connect} from 'react-redux';
import {replace, push} from 'react-router-redux';
class SystemMenu extends React.Component {
constructor(props) {
super(props);
this.logout = this.logout.bind(this);
}
logout() {
this.props.logout();
}
render() {
return (
<ul className="system-menu">
<li className={this.isActual("/system/profile")}>
<Link to="/system/profile">Profile</Link>
</li>
<li className={this.isActual("/system/unit")}>
<Link to="/system/unit">Units</Link>
</li>
<li>
<button onClick={this.logout}>Logout</button>
</li>
</ul>
)
}
}
const mapStateToProps = (state) => {
return {
router: state.router,
actualPage: state.menu.actualPage
};
};
const mapDispatchToProps = (dispatch) => {
return {
logout() {
dispatch(push('/login'));
}
};
};
export default connect(mapStateToProps, mapDispatchToProps)(SystemMenu);
When I click que Link component, pages is changing, But when I click the Logout button to debug, is executing dispatch(push('/login')); line, but nothing has happening, and no occur any error in the console.
What I worse in the configuration?
I tried console.log the logout inside the mapDispatchToProps function, and returning logout is not defined
const mapDispatchToProps = (dispatch) => {
console.log(push, logout);
return {
logout() {
dispatch(push('/login'));
}
};
};
combineReducers should take an object as the first argument, like this:
const store = createStore(
combineReducers({
...reducers,
routing: routerReducer
})
)
You're giving it an Array instead.
I suspect the reason why push doesn't work is because the router reducer is not registered properly.
I resolved this problem.
This problem is occurring because I has not using react-routerredux` middleware, so when I dispatching, maybe is not updating browser URL by state.
Following my route configuration:
import {Provider} from 'react-redux'
import {Router, browserHistory} from 'react-router'
import {createStore, combineReducers, applyMiddleware} from 'redux'
import {routerReducer} from 'react-router-redux';
import {syncHistoryWithStore, routerMiddleware} from 'react-router-redux'
import Reducers from './reducers'; // contains all my reducers,
const middleware = [routerMiddleware(browserHistory)];
const store = createStore(combineReducers(Reducers), compose(
applyMiddleware(...middleware)
));
const history = syncHistoryWithStore(browserHistory, store);
const AppRoute = (
<Provider store={store}>
<Router history={history}>
<Route path='login' components={PageLogin}/>
<Route path='system' components={PageSystem}>
<Route path="profile" component={PageProfile}/>
</Route>
</Router>
</Provider>
);
export default AppRoute;