3

I am using react-redux and I am having a issue where I loose my redux state when the page is refreshed.

Now before I go further on that this is the scenario, which I may be messing up.

Question one: Can I connect to more than one layout?

I have a dashboard and a "app" layout. Both have separate layouts. I connect both in the same manner:

import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import * as actionCreators from '../actions/actionCreators';

function mapStateToProps(state) {
  return {
    profile: state.profile,
    child: state.child,
  }
}

function mapDispachToProps(dispatch) {
  return bindActionCreators(actionCreators, dispatch);
}

const LayoutApp = connect(mapStateToProps, mapDispachToProps)      (DashboardLayout);

export default LayoutApp;

The dashboard connects just fine. I am able to hit reducers when i need to and update the store, however the dashboard links to the app for certain parts of data manipulation for you to play with. When it links I get the data in props as expected, however as soon as any page refreshes within the app layouts I loose the props being sent by maptoprops.

I have tried to combine into one master layout however that seems to have the same affect. I have also tried to save to state immediately when i first receive data but that seems to be lost as well upon refresh which makes me think it is resetting it.

Summary: - DashboardLayout (connects to redux) - AppLayout (connects to redux) however after a page refresh it looses props to the Applayout and needed data is gone.

eip56
  • 63
  • 1
  • 1
  • 8
  • The state only exists during the lifetime of your initial page load. You can persist the state and rehydrate it with `redux-persist`. – Mario Tacke Oct 12 '16 at 19:27
  • 2
    Note that redux-persist, mentioned by @MarioTacke there is just one of the dozens of options you have. You can persist your state tree to server, local storage, cookie, whatever you want (and will fit the medium). The point remains - by default state tree cannot survive page reload on its own, it needs to be saved somewhere. – WTK Oct 12 '16 at 20:26
  • Why don't you create a state in the hierarchy above these two layouts? – Pineda Nov 01 '16 at 22:40
  • Why don't you create a state in the hierarchy above these two layouts? – Pineda Nov 01 '16 at 22:54
  • Possible duplicate of [How can I persist redux state tree on refresh?](https://stackoverflow.com/questions/37195590/how-can-i-persist-redux-state-tree-on-refresh) – Michael Freidgeim Aug 27 '19 at 13:55

4 Answers4

2

Get to know redux-persist

https://github.com/rt2zz/redux-persist

You can install it using

npm i --save redux-persist

persistStore is the function that allows you to persist store.

import {persistStore} from 'redux-persist'

and autoRehydrate is the action that is performed whenever the state needs to be rehydrated

import {autoRehydrate} from 'redux-persist'

following is the structure that may be useful.

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

// add `autoRehydrate` as an enhancer to your store (note:  `autoRehydrate` is not a middleware)
const store = createStore(
     reducer,
     undefined,
     compose(
        applyMiddleware(...),
        autoRehydrate()
     )
)

// begin periodically persisting the store
persistStore(store)

and then for your reducer

 import {REHYDRATE} from 'redux-persist/constants'
 //...
 case REHYDRATE:
   var incoming = action.payload.myReducer
   if (incoming) return {...state, ...incoming, specialKey: 
       processSpecial(incoming.specialKey)}
   return state

following are the methods which can be used to work out of redux-persist

   persistor.pause() - pauses redux persist
   persistor.resume() - resumes redux persist
   persistor.purge() - deletes all persisted data
   persistor.rehydrate() - calls reducer to rehydrate store

types of storage redux persist allows

// sessionStorage
import { persistStore } from 'redux-persist'
import { asyncSessionStorage } from 'redux-persist/storages'    
persistStore(store, {storage: asyncSessionStorage})

// react-native
import {AsyncStorage} from 'react-native'
persistStore(store, {storage: AsyncStorage})

// web with recommended localForage
import localForage from 'localforage'
persistStore(store, {storage: localForage})

it is the most basic use redux-persist hope it helps.

Shivansh Singh
  • 192
  • 1
  • 1
  • 11
0

You can connect to as many components as you want to same store properties - that's not issue. Just to note here, connect is listening for changes so when action changes store it would cause all components listening to changed store parts to re-render (or at least do computation and then compare shadowdom).

Store is stored only when running application - after page close/resfresh it's cleared.

There is good thread about persistence of store (eg. to local storage): Where to write to localStorage in a Redux app?

Community
  • 1
  • 1
Jurosh
  • 4,167
  • 5
  • 32
  • 50
0

As mentioned in the previous answers storing the state in local storage is one possible solution however some other possible solutions are

  1. Make sure your links use the Push API ie <Link to={"route"}/> (react-router) this will ensure the store is not removed between route changes

  2. Set your initial state when you create your store

const rootReducer = combineReducers({
  todos: todos,
  visibilityFilter: visibilityFilter
});

const initialState = { 
  todos: [{id:123, text:'hello', completed: false}] 
};

const store = createStore(
  rootReducer, 
  initialState
);

This will hydrate your reduce store when it is initialized

  1. There are some other libs/frameworks/boilerplates that you could use that also implement server rendering with will render the HTML to the page on the initial render and then load React once the DOM has loaded some of this libs are

Next.js,Electroide,react-redux-universal-hot-example

Going down this route will add significant complexity to your app so you should weigh up the pros and cons before embarking down this route

user1095118
  • 3,480
  • 3
  • 21
  • 19
0

I had this problem, so as somebody mentioned here, i used the localStorage.

In my reducer, i did like this:

const exampleKey = "_exampleKey"

const INITIAL_STATE = {
    example: JSON.parse(localStorage.getItem(exampleKey))
};

export default (state = INITIAL_STATE, action) => {
    switch (action.type) {
        case 'SET_TRUE':
            localStorage.setItem( exampleKey, JSON.stringify(true));
            return { ...state, example: true  };
        case 'SET_FALSE':
            localStorage.setItem( exampleKey, JSON.stringify(false));
            return { ...state, example: false};
        default:
            return state
}

Pointing INITIAL_VALUES.example to localStorage's item example ensure us to keep the correct value when the page reloads.

Hope it helps somebody.