I have a Redux store with this structure:
{ui: {
drawer: false,
dialog: false
},
other_0: {
other_0_0: false,
other_0_1: 'and'
},
other_1: {
other_1_0: null,
other_1_1: true
}
}
I'd like to persist only the key drawer.
My code so far:
import { applyMiddleware, combineReducers, createStore } from "redux";
import thunk from "redux-thunk";
import { persistStore, persistReducer } from "redux-persist";
import storage from "redux-persist/lib/storage";
import logger from "redux-logger";
import other_0_reducer from "./other_0_reducer";
import other_1_reducer from "./other_1_reducer";
import ui_reducer from "./ui_reducer";
const rootReducer = combineReducers({
other_0: other_0_reducer,
other_1: other_1_reducer,
ui: ui_reducer,
});
const pConfig = {
key: "root",
storage: storage,
whitelist: ["ui"]
};
const pReducer = persistReducer(pConfig, rootReducer);
const store = createStore(pReducer, applyMiddleware(thunk, logger));
let persistor = persistStore(store);
export { store, persistor };
This keeps alive the parent key "ui" but in reality I'd like to blacklist the child "dialog".
It's basically a nested persistor: I looked at other articles on StackOverflow but I can't make it work. Can someone help me, please? Thanks!
You can persist each reducer separately.
import { applyMiddleware, combineReducers, createStore } from "redux";
import thunk from "redux-thunk";
import { persistStore, persistReducer } from "redux-persist";
import storage from "redux-persist/lib/storage";
import logger from "redux-logger";
import other_0_reducer from "./other_0_reducer";
import other_1_reducer from "./other_1_reducer";
import ui_reducer from "./ui_reducer";
const uiPersistConfig = {
key: "ui",
storage: storage,
whitelist: ["drawer"]
}
const rootReducer = combineReducers({
other_0: other_0_reducer,
other_1: other_1_reducer,
ui: persistReducer(uiPersistConfig, ui_reducer)
});
const pConfig = {
key: "root",
storage: storage,
whitelist: []
};
const pReducer = persistReducer(pConfig, rootReducer);
const store = createStore(pReducer, applyMiddleware(thunk, logger));
let persistor = persistStore(store);
export { store, persistor };
Hope this helps.
Related
I tried to implement Redux-Persist and this is the code I wrote:
import { createStore, combineReducers } from 'redux';
import { usersReducer } from './users';
import { eventsReducer } from './events';
import { persistStore, persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
const persistConfig = {
key: 'root',
storage
}
const reducer = combineReducers({ users: usersReducer, events: eventsReducer })
const persistedReducer = persistReducer(persistConfig, reducer);
const store = createStore(persistedReducer);
const persistor = persistStore(store);
export { store, persistor };
My store.js file:
import { createStore, combineReducers } from 'redux';
import { usersReducer } from './users';
import { eventsReducer } from './events';
import { persistStore, persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
const persistConfig = {
key: 'root',
storage
}
const reducer = combineReducers({ users: usersReducer, events: eventsReducer })
const persistedReducer = persistReducer(persistConfig, reducer);
const store = createStore(persistedReducer);
const persistor = persistStore(store);
export { store, persistor };
My usersReducer.js file (eventsReducer.js is built like this one):
const initialState = {
loggedIn: false,
thisUser: []
}
export function usersReducer(state = initialState, action) {
switch (action.type) {
case 'users/loggedIn':
return { ...state, loggedIn: action.payload }
case 'users/addUser':
return { ...state, thisUser: action.payload[0] }
case 'users/setActivated':
return { ...state, thisUser: { ...state.thisUser, activated: action.payload } }
case 'clearAll':
return {
thisUser: []
}
default:
return state
}
}
My index.js file:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { Provider } from 'react-redux'
import { store, persistor } from './store/store';
import { PersistGate } from 'redux-persist/integration/react'
ReactDOM.render(
<Provider store={store}>
<PersistGate persistor={persistor}>
<App />
</PersistGate>
</Provider>,
document.getElementById('root')
);
My problem is: Redux-Persist works and is saved in localStorage, but when I refresh the page, my data saved in localStorage with Redux-Persist don't update my local state and will be empty. I think that on any refresh of the page I should get persisted data from localStorage and send back into my Redux state.
I don't know if is correct what I say but I need help how to resolve this problem.
I'm trying to convert
react redux
to its counterpart
react redux toolkit
but i kept running into this problem
t is not a function. (In 't(i,c)', 't' is an instance of Object)
And I don't really understand what it means.
This is the configureStore.js
import { configureStore } from '#reduxjs/toolkit'
import { persistStore, persistReducer, FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER,} from 'redux-persist'
import AsyncStorage from '#react-native-community/async-storage';
import { createLogger } from 'redux-logger';
import createSagaMiddleware from 'redux-saga';
//import sagas from 'app/sagas';
import {
loginReducer,
paymentReducer,
signupReducer
} from '../reducer';
const config = {
key: 'root',
storage: AsyncStorage,
blacklist: ['loadingReducer'],
debug: true, //to get useful logging
};
const middleware = [];
const sagaMiddleware = createSagaMiddleware();
middleware.push(sagaMiddleware);
if (__DEV__) {
middleware.push(createLogger());
}
const reducers = persistReducer(config, {reducer:{
loginReducer,
signupReducer,
paymentReducer
}})
const store = configureStore({
reducer: reducers,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: {
ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
},
thunk: false,
...middleware
}),
})
let persistor = persistStore(store);
const myStore = () => {
return { persistor, store };
};
export default myStore
//sagaMiddleware.run(sagas);
/*import { configureStore } from '#reduxjs/toolkit'
export const store = configureStore({
reducer: {},
})
while this is
App.js
import React from 'react';
import { ActivityIndicator } from 'react-native';
import { Provider } from 'react-redux';
import storage from 'redux-persist/lib/storage'
import { PersistGate } from 'redux-persist/integration/react'
import { DefaultTheme, Provider as PaperProvider } from 'react-native-paper';
import 'react-native-gesture-handler';
import Navigator from './app/navigation';
import myStore from './app/store/configureStore';
import { enableScreens } from 'react-native-screens';
enableScreens();
const { persistor, store } = myStore();
const theme = {
...DefaultTheme,
roundness: 2,
colors: {
...DefaultTheme.colors,
// primary: '#3498db',
// accent: '#f1c40f',
},
};
export default function Entrypoint() {
return (
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<PaperProvider theme={theme}>
<Navigator />
</PaperProvider>
</PersistGate>
</Provider>
);
}
I don't know where the problem is but
I'm quite sure the problem is in the configureStore script
How do I solve this kind of issue
I had a similar issue when moving from Redux to Redux Toolkit. It seems that removing the redux and react-redux packages before installing Redux Toolkit fixed the issue I was having (o.configureStore is not a function).
Also, your middleware is not in line with how the documentation writes it, it should be:
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: {
ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
},
thunk: false
})
.concat(middleware)
I didn't use persist-redux nor Redux Saga though, maybe there's something else.
I started doing the typing of my redux and ran into such a problem, namely the typing of useSelector
Here is the hook I'm creating:
import {TypedUseSelectorHook, useSelector} from 'react-redux'
import {RootState} from '../store/create-reducer'
export const UseTypedSelector: TypedUseSelectorHook <RootState> = useSelector
And he returns me an error:
screen
How to solve this problem? For the second day I can't get off the ground, and using useSelector ((state: any) => state? .SESSION) is not an option.
Here is my side:
create-reducer:
import { combineReducers } from 'redux'
import { STATE } from '../session/types'
import { reducer } from '../session/reducers'
const rootReducer = (asyncReducers: object) => {
return (
combineReducers({
...asyncReducers,
[STATE]: reducer,
})
)
}
export default rootReducer
export type RootState = ReturnType<typeof rootReducer>
create-store:
import { applyMiddleware, compose, createStore } from 'redux'
import thunk from 'redux-thunk'
import persistStore from './persist-store'
import persistReducer from './persist-reducer'
const store = (initialState = {}) => {
const middlewares = [thunk]
const enhancers: Array<any> = []
const store = createStore(
persistReducer({}),
initialState,
compose(applyMiddleware(...middlewares), ...enhancers),
)
const persistor = persistStore(store)
return { store, persistor }
}
export default store
index:
export { default as createReducer } from './create-reducer'
export { default as createStore } from './create-store'
export { default as persistReducer } from './persist-reducer'
persist-reducer:
import { persistReducer } from 'redux-persist'
import storage from 'redux-persist/lib/storage'
import createReducer from './create-reducer'
const persistConfig = { key: 'myproject', storage, whitelist: ['session'] }
const reducer = (asyncReducers: any) => persistReducer(persistConfig, createReducer(asyncReducers))
export default reducer
persist-store:
import { persistStore } from 'redux-persist'
const store = (store: any) => persistStore(store, null, () => {})
export default store
So I've got a react redux app and using the 'blacklist' parameter to not rehydrate a couple of reducers. However, upon refresh it completely removes the entire reducer rather than them being set to their initial states. The reducers initial states are fine when not using redux persist. This is the index file of the store:
import { createStore, applyMiddleware, compose } from "redux";
import createSagaMiddleware from "redux-saga";
import rootReducer from "./reducers";
import rootSaga from "./sagas";
import thunk from "redux-thunk";
import logger from "redux-logger";
import { persistStore, persistReducer } from "redux-persist";
import storage from "redux-persist/lib/storage";
import hardSet from "redux-persist/lib/stateReconciler/hardSet";
const persistConfig = {
key: "root",
storage,
stateReconciler: hardSet,
blacklist: ["Alerts", "Layout", "JourneyData"]
};
const persistedReducer = persistReducer(persistConfig, rootReducer);
const sagaMiddleware = createSagaMiddleware();
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const middleWares = [sagaMiddleware, thunk];
const store = createStore(
persistedReducer,
composeEnhancers(applyMiddleware(...middleWares, logger))
);
export const persistor = persistStore(store);
sagaMiddleware.run(rootSaga);
export default store;
I want to blacklist some of my reducers because my state tree is getting bigger and im getting this error:
Could not write debug session to localStorage: DOMException: Failed to execute 'setItem' on 'Storage': Setting the value of 'redux-persist' exceeded the quota.(…)"
The solution I found is to blacklist some reducers that doesn't need to be persisted. So I have this code in my App.js
import React, { Component } from 'react';
import { Provider } from 'react-redux';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import { persistStore } from 'redux-persist'
import { Initializer } from './components';
import store from './store';
class App extends Component {
constructor() {
super()
this.state = { rehydrated: false }
}
componentWillMount(){
persistStore(store, { blacklist: ['project', 'comment', 'project', 'jobOrder']}, () => {
this.setState({ rehydrated: true })
})
}
render() {
if(!this.state.rehydrated)
return <Initializer />;
return (
<Provider store={store}>
<Router>
<div>
<Switch>
... some Routes
</Switch>
</div>
</Router>
</Provider>
);
}
}
export default App;
and I have this rootReducer:
import { reducer as formReducer } from 'redux-form'
import { combineReducers } from 'redux';
import userAuthReducer from './userAuthReducer';
import jobOrderReducer from './jobOrderReducer';
import clientReducer from './clientReducer';
import userReducer from './userReducer';
import persistReducer from './persistReducer';
import commentReducer from './commentReducer';
import projectReducer from './projectReducer';
import teamReducer from './teamReducer';
export default combineReducers({
userAuth: userAuthReducer,
jobOrder: jobOrderReducer,
job_order: jobOrderReducer,
client: clientReducer,
user: userReducer,
form: formReducer,
persist: persistReducer,
comment: commentReducer,
project: projectReducer,
team: teamReducer
});
My persistReducer.js
import { PERSIST } from '../actions/types';
export default (state = [], action) => {
switch(action.type) {
case PERSIST:
return { ...state, ...action.payload }
default:
return state;
}
};
And my store.js
import { compose, createStore, applyMiddleware } from 'redux';
import { autoRehydrate } from 'redux-persist';
import thunk from 'redux-thunk';
//import logger from 'redux-logger';
import rootReducer from './reducers';
const store = createStore(
rootReducer,
{},
compose(
applyMiddleware(thunk, /*logger*/),
autoRehydrate())
);
//persistStore(store);
export default store;
But running the App, I still get the blacklisted persisted state as you can see here:
I tried changing the blacklist keys to:
persistStore(store, { blacklist: ['reduxPersist:project', 'reduxPersist:comment', 'reduxPersist:project', 'reduxPersist:jobOrder']}, () => {
this.setState({ rehydrated: true })
})
But the keys are still persisting... How to properly do this?
I read this article here and the author made a good point, the blacklist isn't looking for the name of the attributes in your redux store, rather in your state. I had the same confusion.
Double check in dev tools what is actually being saved in your local storage. make sure you are blacklisting the correct names.
You need to define blacklist array in both config objects (parent and child).
const rootPersistConfig = {
key: 'root',
storage: AsyncStorage,
blacklist: ['appReducer'], // 2: Need to add child reducer key here too.
};
const appPersistConfig = {
key: 'appReducer',
storage: AsyncStorage,
// 1: Below are the keys to blacklist
blacklist: ['snackbar', 'dayThought', 'updatingBohoId', 'snackbar_notif'],
};