Redux persist blacklist deleting reducers? - javascript

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;

Related

Nested Redux persistor

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.

Redux thunk, difference between using it as a list or as an object

I'm reading a code of a react project I found on GitHub and I found a different use of redux thunk, by seeing the official documentation at GitHub they use it this way:
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers/index';
// Note: this API requires redux#>=3.1.0
const store = createStore(
rootReducer,
applyMiddleware(thunk)
);
but in the code I found the guy used:
import { AsyncStorage } from 'react-native';
import { applyMiddleware, createStore } from 'redux';
import { autoRehydrate, persistStore } from 'redux-persist'
import thunk from 'redux-thunk';
import reducers from '../reducers';
const middleWare = [thunk];
const createStoreWithMiddleware = applyMiddleware(...middleWare)(createStore);
export default configureStore = (onComplete) => {
const store = autoRehydrate()(createStoreWithMiddleware)(reducers);
persistStore(store, { storage: AsyncStorage }, onComplete);
return store;
};
what is the difference between using it as a list or as an object?
Let's look at the function signature (source):
function applyMiddleware(...middlewares) { /* logic */ }
applyMiddleware uses the rest parameter syntax which allows representing an indefinite number of arguments as an array.
Because of this, both
applyMiddleware(thunk, otherMiddleware);
and
const middlewares = [thunk, otherMiddleware];
applyMiddleware(...middlewares);
are equally valid.

conditionally load different reducers into redux store

I have a function that check the role of a user. I want to base on that pass different reducer into a store, is that possible?
import { createStore, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
import { getUserRole } from './utils'
import { composeWithDevTools } from 'redux-devtools-extension'
import userReducers from './reducers'
import adminReducers from './reducers/admin'
//share reducer btw member and admin
let reducers
if (getUserRole() === 'member') {
reducers = userReducers
} else {
reducers = adminReducers
}
console.log('reducers', reducers) //undefined unless I refresh the page
const store = createStore(
reducers,
composeWithDevTools(
applyMiddleware(thunk)
)
)
export default store
I found a problem, reducers is undefined for the first time (like I login) unless I refresh it.

Reducers are gone after attempting to implement redux-persist

I am attempting to implement redux-persist to persist a specific reducer only, invoices, version, but in my case, my reducers are all gone.
This is the entry point:
import React, { Component } from "react";
import { Provider } from "react-redux";
import { createStore, applyMiddleware, compose } from "redux";
import { persistStore, persistCombineReducers } from "redux-persist";
import { createWhitelistFilter } from "redux-persist-transform-filter";
import { PersistGate } from 'redux-persist/es/integration/react';
import storage from "redux-persist/lib/storage";
import thunkMiddleware from "redux-thunk";
import { apiMiddleware } from "redux-api-middleware";
import reducers from "./actions/reducers";
import AppContainer from "./containers/App";
import FlashMessage from "./containers/common/FlashMessage";
import "./App.css"
const middleware = [thunkMiddleware, apiMiddleware];
const persistConfig = {
storage,
key: 'root',
transforms: [
createWhitelistFilter('invoices')
]
};
const store = createStore(
persistCombineReducers(persistConfig, reducers),
compose(
applyMiddleware(...middleware),
)
);
const persistor = persistStore(store);
export default class App extends Component {
render () {
return (
<Provider store={store}>
<PersistGate persistor={persistor}>
{/*<FlashMessage/>*/} // Since there is no reducer, this fails
<AppContainer/>
</PersistGate>
</Provider>
)
}
}
And this is the reducers file I have:
import { combineReducers } from "redux";
import { routerReducer as router } from "react-router-redux";
import app from "./app";
import invoices from "./invoices/invoices";
import recipients from "./recipients/recipients";
export const makeRootReducer = (asyncReducers) => {
return combineReducers({
router,
app,
invoices,
recipients,
...asyncReducers
})
};
export const injectReducer = (store, { key, reducer }) => {
store.asyncReducers[key] = reducer;
store.replaceReducer(makeRootReducer(store.asyncReducers))
};
export default makeRootReducer;
I have followed many suggestions but I must be missing something.
I found out why. After checking the source code, I saw the following documentation block of persistCombineReducers:
/**
* It provides a way of combining the reducers, replacing redux's #see combineReducers
* #param config persistence configuration
* #param reducers set of keyed functions mapping to the application state
* #returns reducer
*/
export function persistCombineReducers<S>(config: PersistConfig, reducers: ReducersMapObject): Reducer<S & PersistedState>;
The key words were "replacing redux's #see combineReducers".
Removing combineReducers from my reducers file to the following solved the issue:
import { routerReducer as router } from "react-router-redux";
import app from "./app";
import invoices from "./invoices/invoices";
import recipients from "./recipients/recipients";
const reducers = {
router,
app,
invoices,
recipients,
};
export default reducers;

How persist redux store to localstorage

can't persist store to localstorage, using redux-persist.
Have error:
Store does not have a valid reducer. Make sure the argument passed to
combineReducers is an object whose values are reducers.
Help pls to configure store or are there another ways
import {applyMiddleware, compose, createStore} from "redux";
import thunk from "redux-thunk";
import {createLogger} from "redux-logger";
import rootReducer from "../reducer/index";
import {loadState, saveState} from "../utils";
import { persistStore, persistCombineReducers } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
const config = {
key: 'root',
storage,
}
const reducer = persistCombineReducers(config, rootReducer)
function configureStore(initialState) {
let createStoreWithMiddleware;
const middleware = process.env.__DEV__
? applyMiddleware(thunk, createLogger())
: applyMiddleware(thunk);
createStoreWithMiddleware = compose(
middleware,
);
const store = createStoreWithMiddleware(createStore)(reducer, initialState);
let persistor = persistStore(store)
if (module.hot) {
module.hot
.accept('../reducer', () => {
const nextRootReducer = require('../reducer/index');
store.replaceReducer(nextRootReducer);
});
}
store.subscribe(() => {
saveState(store.getState().albums)
});
return {store, persistor};
}
export default configureStore
As the error message is already telling - you have to pass an object to the persistCombineReducers method.
Please have a look at the following example. (Some of your code is commented there to have a minimal example.)
So the code of your combined reducer could be like this:
const reducer = persistCombineReducers(config, {root: rootReducer});
const store = createStore(reducer, initialState);
If you're only having one reducer it would be better to use:
const reducer = persistReducer(config, rootReducer);

Categories

Resources