question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Persist Redux State Across Page Refresh

See original GitHub issue

This is pointed towards the redux and Apollo branches: as things are so now, a page refresh will return the store to it’s initial state.

Has anyone implement something like redux-persist with this boilerplate?

How can I make the redux store state persist across a page refresh with SSR?

What I have done so far:

Add autoRehydrate function to /src/store/configureStore.js

import { createStore, applyMiddleware, compose } from 'redux';
import { autoRehydrate } from 'redux-persist';

{...}

if (__DEV__) {
    middleware.push(createLogger());

    // https://github.com/zalmoxisus/redux-devtools-extension#redux-devtools-extension
    let devToolsExtension = f => f;
    if (process.env.BROWSER && window.devToolsExtension) {
      devToolsExtension = window.devToolsExtension();
    }

    enhancer = compose(
      applyMiddleware(...middleware),
      autoRehydrate(),
      devToolsExtension,
    );
  } else {
    enhancer = compose(
      applyMiddleware(...middleware),
      autoRehydrate(),
    );
  }
{ ... }

Create action/reducer for persist/REHYDRATE

/src/actions/persisteRehydrate

import { PERSIST_REHYDRATE } from '../constants';

export function updateUserInfo({ name, value }) {
  return {
    type: PERSIST_REHYDRATE,
    payload: {
      name,
      value,
    },
  };
}

/src/reducers/persistRehydrate

import { PERSIST_REHYDRATE } from '../constants';

export default function persistRehydrate(state = {}, action) {
  switch (action.type) {
    case PERSIST_REHYDRATE:
      return {
        ...state,
        [action.payload.name]: action.payload.value,
      };
    default:
      return state;
  }
}

Add persistStore function to /src/client.js

import { persistStore } from 'redux-persist';

{ ... }

const store = configureStore(undefined, {
  apolloClient,
  fetch,
  history
});

persistStore(store, {storage: localForage}, () => {
  console.log("resolved!");
});

const context = {
  // Enables critical path CSS rendering
  // https://github.com/kriasoft/isomorphic-style-loader
  insertCss: (...styles) => {
    // eslint-disable-next-line no-underscore-dangle
    const removeCss = styles.map(x => x._insertCss());
    return () => { removeCss.forEach(f => f()); };
  },
  // For react-apollo
  client: apolloClient,
  // Initialize a new Redux store
  // http://redux.js.org/docs/basics/UsageWithReact.html
  store: store,
  fetch,
  storeSubscription: null,
};

{ ... }

Rehydration appears to be working with the above code, but the problem now is that it takes some time to rehydrate the store on the client side, routes start evaluating before the store is rehydrated which causes problems, so the application must wait for rehydration before continuing

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:7

github_iconTop GitHub Comments

3reactions
lviancommented, Sep 21, 2017

Hey @tim-soft , thanks for posting.

What version of redux-persist you were using? I just implemented v5 of it on my project with the foillowing code changes to configureStore.js.

import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from '../reducers';
import createHelpers from './createHelpers';
import createLogger from './logger';
import {persistStore, autoRehydrate} from 'redux-persist'

export default function configureStore(initialState, helpersConfig) {
  const helpers = createHelpers(helpersConfig);
  const middleware = [thunk.withExtraArgument(helpers)];

  let enhancer;

  if (__DEV__) {
    //Thunk and redux-persist
    middleware.push(createLogger());
    

    // https://github.com/zalmoxisus/redux-devtools-extension#redux-devtools-extension
    let devToolsExtension = f => f;
    if (process.env.BROWSER && window.devToolsExtension) {
      devToolsExtension = window.devToolsExtension();
    }

    enhancer = compose(applyMiddleware(...middleware), autoRehydrate() , devToolsExtension);
  } else {
    enhancer = compose(applyMiddleware(...middleware) , autoRehydrate() );
  }

  // See https://github.com/rackt/redux/releases/tag/v3.1.0
  const store = createStore(rootReducer, initialState, enhancer);

  // begin periodically persisting the store
  persistStore(store)

  // Hot reload reducers (requires Webpack or Browserify HMR to be enabled)
  if (__DEV__ && module.hot) {
    module.hot.accept('../reducers', () =>
      // eslint-disable-next-line global-require
      store.replaceReducer(require('../reducers').default),
    );
  }

  return store;
}

Working well so far, no need to any additional reducer/actions.

Next problem I’m tackling is the fact that page redirection based on store parameters will kick in before the rehydrate can happen, any advice is welcome.

0reactions
tim-softcommented, Mar 25, 2018

@langpavel saving things like tab keys in the URL usually make sense. React components lose their state when the re-render, I’m thinking about situations where there is a lot of UI state to remember across re-renders/refreshes that I also wouldn’t want to replicate when users share URLs. Managing a lot of stuff in redux is a lot more practical than URL vars/fragments

Read more comments on GitHub >

github_iconTop Results From Across the Web

How can I persist redux state tree on refresh? - Stack Overflow
If you would like to persist your redux state across a browser refresh, it's best to do this using redux middleware.
Read more >
Persist state with Redux Persist using Redux Toolkit in React
When we refresh the browser, our data will be lost. Let's learn how to use Redux Persist to save the state in persistent...
Read more >
Persist Redux State with redux-persist - DEV Community ‍ ‍
When we refresh page in a web-app, the state always resets back to the initial values which in not a... Tagged with react,...
Read more >
5 Methods to Persisting State Between Page Reloads in React
One of the straightforward options is to use localStorage in the browser to persist the state. Let's take a look at an example....
Read more >
How to persist Redux state in local Storage without any ...
The idea to use Redux may be fine for a complex react app but this state is not persistable throughout. It means that...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found