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.

State lost after page reload. How to resolve this?

See original GitHub issue

OS: Windows 10 Pro
redux-persist: “^4.8.0”

So after a reload of any of my Router paths is made, state becomes === undefined. But I want the state, as of that moment in time, to remain intact after a page reload. How do I ensure that this happens?

app.js

render(
  <ApolloProvider store={store} client={client}>
    { /* Tell the Router to use our enhanced history */ }
    <Router history={history}>
      <Route path="/" component={App}>
        <IndexRoute component={PhotoGrid} />
        <Route path="/view/:postId" component={Single}></Route>
        <Route path="/login" component={LoginUser}></Route>
      </Route>
    </Router>
  </ApolloProvider>,
  document.getElementById('root')
);

store.js

import { persistStore, autoRehydrate} from 'redux-persist';
import rootReducer from './reducers/index';
import localForage from 'localforage';

const middlewares = [thunk, client.middleware()];

const enhancers = compose(
    applyMiddleware(...middlewares),
    (typeof window.__REDUX_DEVTOOLS_EXTENSION__ !== 'undefined' || process.env.NODE_ENV !== 'production') ? window.__REDUX_DEVTOOLS_EXTENSION__() : (f) => f,
    autoRehydrate(),
);

const defaultState = {
  auth: {}
};

const store = createStore(
  rootReducer,
  undefined, // {}, // initial state
  enhancers
);

// begin periodically persisting the store
persistStore(store, {storage: localForage});

export const history = syncHistoryWithStore(
  browserHistory, 
  store
);

if(module.hot) {
  module.hot.accept('./reducers/', () => {
    const nextRootReducer = require('./reducers/index').default;
    store.replaceReducer(nextRootReducer);
  });
}

export default store;

index.js (Root reducer)

const rootReducer = combineReducers({
  auth: tokenDetails,
  logout: logOut,
  routing: routerReducer,
  apollo: client.reducer(),
});

export default rootReducer;

App.js

const allPostsCommentsQuery = graphql(All_Posts_Comments_Query, {
  options: {
    cachePolicy: 'offline-critical', 
    fetchPolicy: 'cache-first',
  },
});

function mapStateToProps(state) {
   return {
    auth: state.auth
  };
}

export const mapDispatchToProps = (dispatch) => {
  return bindActionCreators(actionCreators, dispatch);
}

export default compose(
  allPostsCommentsQuery,
  connect(mapStateToProps, mapDispatchToProps)
)(Main);

tokenDetials.js (Reducer)

var tokenDetails = function(state, action) {

  if (state === undefined) {
    console.log('state = undefined, in tokenDetails.js, and has been reset to {}');
    state = {};
  }

  switch (action.type) {
    case 'Graphcool_Token':
      const newState = { ...state, token: action.payload };
      // console.log('newState = ', newState);
      return newState;
    default:
      return state;
  }
}

export default tokenDetails;

And do I need to do something like the following in each of my components to ensure that state is persisted, or is persistStore(store, {storage: localForage}); specified in my store.js enough?:

  componentWillMount () {
    persistStore(this.props.store, {storage: Localforage}, () => {
      this.setState({ rehydrated: true })
    })
  }

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Reactions:12
  • Comments:5

github_iconTop GitHub Comments

5reactions
absercommented, Sep 11, 2017

For me below works fine.

  • Configure store
  • import store before in ReactDom.Render
  • persist the store, after rehydration I am rendering dom.
...................
import configureStore from './store';
import {persistStore, autoRehydrate} from 'redux-persist'

const store =  configureStore();
persistStore(store, {}, () => {
  ReactDOM.render((
    <Provider store={store}>
      <Router>
        <App/>
      </Router>
    </Provider>
  ), document.getElementById('root'));
  registerServiceWorker();  
})
3reactions
TheoMercommented, Jun 3, 2017

@glowind Solution found.

Rehydration was not working due to the order of autoRehydrate() in my enhancers in store.js. It MUST appear before devTools!

const enhancers = compose(
    applyMiddleware(...middlewares),
    autoRehydrate(),
    (typeof window.__REDUX_DEVTOOLS_EXTENSION__ !== 'undefined' || process.env.NODE_ENV !== 'production') ? window.__REDUX_DEVTOOLS_EXTENSION__() : (f) => f,
);

I was able to then remove all of the rehydrate code from my main component (router), so it reads as follows:

class MainApp extends React.Component {
  constructor(props) {
    super(props);
  }

  render () {
    return (
      <ApolloProvider store={store} client={client}>
        <Router history={history}>
          <Route path="/" component={App}>
            <IndexRoute component={PhotoGrid} />
            <Route path="/view/:postId" component={Single}></Route>
            <Route path="/login" component={LoginUser}></Route>
          </Route>
        </Router>
      </ApolloProvider>
    )
  }
}

export default MainApp;

And all works as expected now.

Read more comments on GitHub >

github_iconTop Results From Across the Web

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 maintain state after a page refresh in React.js?
You can "persist" the state using local storage as Omar Suggest, but it should be done once the state ...
Read more >
How to Save State to LocalStorage & Persist on Refresh with ...
Step 3: Getting a stored value from localStorage and loading it into React state. Finally to make sure our state is persisted any...
Read more >
How to persist state after a page refresh in React using local ...
Sometimes it is necessary to keep the state of a React component persistent even after a browser refresh. A simple way to accomplish...
Read more >
location.reload() - Web APIs | MDN
The location.reload() method reloads the current URL, like the Refresh button.
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