rt2zz / redux-persist

persist and rehydrate a redux store
MIT License
12.93k stars 866 forks source link

Implementation of redux-persist with react-boilerplate #815

Open tilakgajjar opened 6 years ago

tilakgajjar commented 6 years ago

configureStore.js

import { persistStore, persistReducer } from 'redux-persist';
import createReducer from './reducers';

const persistConfig = {
 transforms: [immutableTransform()],
 key: 'root',
 storage: sessionStorage,
whitelist: ['metaIndexObj'],
 };

const rootReducers = createReducer();
const persistedReducer = persistReducer(persistConfig, rootReducers);

const sagaMiddleware = createSagaMiddleware();

const stateTransformer = (state) => {
if (Iterable.isIterable(state)) return state.toJS();
   return state;
 };

 const logger = createLogger({
     stateTransformer,
     // diff: true,
  });

 export default function configureStore(initialState = {}, history) {
  // Create the store with two middlewares
  // 1. sagaMiddleware: Makes redux-sagas work
  // 2. routerMiddleware: Syncs the location/URL path to the state
  const middlewares = [
     sagaMiddleware,
     routerMiddleware(history),
     logger,
   ];

  const enhancers = [
       applyMiddleware(...middlewares),
   ];

  // If Redux DevTools Extension is installed use it, otherwise use Redux compose
  /* eslint-disable no-underscore-dangle */
  const composeEnhancers =
     process.env.NODE_ENV !== 'production' &&
     typeof window === 'object' &&
     window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
     ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
      // TODO Try to remove when `react-router-redux` is out of beta, LOCATION_CHANGE should not 
     be fired more than once after hot reloading
     // Prevent recomputing reducers for `replaceReducer`
     shouldHotReload: false,
    })
    : compose;
   /* eslint-enable */

  const store = createStore(
   // createReducer(),
   persistedReducer,
   fromJS(initialState),
   composeEnhancers(...enhancers),
   );

  // Extensions
  store.runSaga = sagaMiddleware.run;
  store.injectedReducers = {}; // Reducer registry
  store.injectedSagas = {}; // Saga registry

  // injectSaga('appData', GetMetaIndexEvent.saga);

  // Make reducers hot reloadable, see http://mxs.is/googmo
  /* istanbul ignore next */
 if (module.hot) {
   module.hot.accept('./reducers', () => {
   store.replaceReducer(createReducer(store.injectedReducers));
   });
 }

 const persistor = persistStore(store);
 return { persistor, store };
 }

reducers.js

import { fromJS } from 'immutable';
import { combineReducers } from 'redux-immutable';
import { LOCATION_CHANGE } from 'react-router-redux';

const routeInitialState = fromJS({
   location: null,
});

 function routeReducer(state = routeInitialState, action) {
 switch (action.type) {
  /* istanbul ignore next */
  case LOCATION_CHANGE:
     return state.merge({
        location: action.payload,
     });
   default:
    return state;
   }
}

 export default function createReducer(injectedReducers) {
 return combineReducers({
    route: routeReducer,
    ...injectedReducers,
  });
}

app.js

const render = () => {
  ReactDOM.render(
   <Provider store={store}>
     <PersistGate persistor={persistor}>
       <ConnectedRouter history={history}>
         <App />
       </ConnectedRouter>
     </PersistGate>
   </Provider>,
   MOUNT_NODE
 );
};

[

screen shot 2018-04-27 at 10 00 36 pm screen shot 2018-04-27 at 10 00 58 pm

](url)

Gyvastis commented 6 years ago

Yeah, I'm struggling with this as well. I think it has something to do with ImmutableJS. In previous redux-persist versions we used to have redux-persist-immutable library to persistStore but now it's not usable in this version.

Farrukhameen commented 6 years ago

Any updates on this issue I am facing the same issue. any solution?

Gyvastis commented 6 years ago

@Farrukhameen ended up using version 4. At least it works as expected.

tilakgajjar commented 6 years ago

I implemented redux persist with this:

https://egghead.io/lessons/javascript-redux-persisting-the-state-to-the-local-storage

sincerekamal commented 6 years ago

@Gyvastis version 4 of redux-persist or what ?

FoxxMD commented 6 years ago

@sincerekamal version 4 of redux-persist works with react-boilerplate

sincerekamal commented 6 years ago

Is there any documentation for that specifically ? because I failed to do it correctly. It would be great to just integrating this into react-boilerplate

FoxxMD commented 6 years ago

For my build

Relevant code in store.js

import { persistStore, autoRehydrate } from 'redux-persist-immutable';
import localForage from 'localforage';

// ...

 const enhancers = [
  applyMiddleware(...middlewares),
  autoRehydrate(),
 ];

// ...

const store = createStore(
    createReducer(),
    fromJS(initialState),
    composeEnhancers(...enhancers)
  );

 window.persistor = persistStore(store, { storage: localForage, whitelist: [/*app-specific keys*/] }, (a, b) => {
     console.log('Redux-Persist loaded state');
   });

store.runSaga = sagaMiddleware.run;
 store.injectedReducers = {};
 store.injectedSagas = {};

// ...

I have more related code but its app-specific. That should be enough to get it working.

EDIT: I assign it to windows.persistor because I want to stop persisting/purge based on user actions later in the app and I couldn't find an easier way to access the persistor. works fine when assigned to window

Macilias commented 5 years ago

obviously you use also https://www.npmjs.com/package/localforage. Anyway I´m new to react/redux and don´t see how to merge this with https://www.npmjs.com/package/redux-persist. The docu on https://www.npmjs.com/package/redux-persist-immutable says it`s a wrapper so some of the original redux-persist need still to be applied, but seams to be incompatible. For eg:

const persistedReducer = persistReducer(persistConfig, rootReducer)

I´m also not sure weather or not once can use the window.persistor like that:

const App = () => {
  return (
    <Provider store={store}>
      <PersistGate loading={null} persistor={window.persistor}>
        <RootComponent />
      </PersistGate>
    </Provider>
  );
};

When it try this I get the exception:

react.js?28cc:53 Uncaught TypeError: this.props.persistor.subscribe is not a function
    at PersistGate.componentDidMount (react.js?28cc:53)
    at commitLifeCycles (react-dom.development.js:14361)
    at commitAllLifeCycles (react-dom.development.js:15462)
    at HTMLUnknownElement.callCallback (react-dom.development.js:100)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:138)
    at invokeGuardedCallback (react-dom.development.js:187)
    at commitRoot (react-dom.development.js:15603)
    at completeRoot (react-dom.development.js:16618)
    at performWorkOnRoot (react-dom.development.js:16563)
    at performWork (react-dom.development.js:16482)

and I´m not the only one: https://github.com/rt2zz/redux-persist/issues/731 A working full example would be great.

FoxxMD commented 5 years ago

localforage was my choice for storage engine yes, but any of the options from the docs can be used.

Redux Persist 5 is a mess. The majority of issues on this repo were created after the release of v5. And no real commits addressing issues have been made since at least June 2018. I tried migrating to v5 on release it was never worked.

I would suggest you stick to the version I mentioned in my comment unless there is something specific you need with v5.

Macilias commented 5 years ago

you are damn right its a mess, just look at this: https://github.com/rt2zz/redux-persist/issues/64 Thanks for the fast reply, I´ll try to find some old documentation for v4 and stick to that.

FoxxMD commented 5 years ago

Here's documentation for 4.10.2

Macilias commented 5 years ago

Thx!

aguynamedben commented 5 years ago

It is a mess. If anybody wants to help with development, bug fixes, or organizing the issues, help would surely be very welcome. I'm trying to at least organize and prioritize the issues with labels, and work through all the old ones. I think @rt2zz has very limited time to spend working on redux-persist, but maybe he could chime in.

panchicore commented 5 years ago

when no need of redux-persist and want to persist you can do this as well: https://github.com/rt2zz/redux-persist/issues/581#issuecomment-491964148

erfoon commented 4 years ago

Anyone knows any solution on this? I know the issue is for like 2 years ago but I couldn't find any way to persist my redux state. Clearly redux-persist is not a solution. I tried to implement it my self using local storage but because the reducers are not loaded in the first place I get this error: Unexpected keys "App", "User" found in preloadedState argument passed to createStore So what should I do? I have written lots of codes using react-boilerplate approach and now the persisting seems impossible :/

aguynamedben commented 4 years ago

@erfansamieyan The thing I've seen mentioned most often, which we haven't done in our code yet because it's all redux-persisted and I'm scared to touch it, is this: https://medium.com/@jrcreencia/persisting-redux-state-to-local-storage-f81eb0b90e7e I've seen multiple smart people say "just throttle it to save once per second" as demonstrated there.

Let me know how it turns out... we might do this soon in my app.

FoxxMD commented 4 years ago

@erfansamieyan my project is using slightly modified react-boilerplate that is as current as november 2019, my persist setup is still the same as my comment above https://github.com/rt2zz/redux-persist/issues/815#issuecomment-408876514 and still works