Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to maintain the state of React/Redux application across page refreshes?

I am new to react js.

I have two routes like A & B. Now i am passing some values from A to B as props. If B page is refreshed, then all props values from A is gone and B page is not rendering. I am using react with redux.

mapDispatchToProps & mapStateToProps functions are used to pass values between A & B routes as props.

For example: Route A has done some calculations and store the values in redux state and Route B is exported as connect(mapStateToProps, mapDispatchToProps)(B), by using mapStateToProps in which A's state values are passed to B as props.

Please suggest me the best way to handle browser refresh on above mentioned use case and also if any other best way to pass the values between routes. Thanks in advance.

like image 874
AndroidKid Avatar asked Jan 05 '23 04:01

AndroidKid


1 Answers

Your question talks about two different concerns. First is passing props from one page to another in a React/Redux application, and second is maintaining the application state when the page is refreshed.

You've described the correct method of passing data between two routes in a redux based application.

Which brings us to the second concern.
How to maintain the state of a React/Redux application when the page is refreshed?

When a React/Redux application is refreshed, it gets initialised again and the redux store gets it's default values.

If you wish to maintain the app state across page refreshes or across different sessions, you need to store the state somewhere, and load it when the app initialises.

We can divide this problem into three parts:

  • Where to store the data
  • How to store redux state
  • How to reload the data when the application is initialised

Let's look at each sub-problem individually.

Where to store the data?

You can use the Web Storage API to store data within the user's browser. This API provides 2 mechanisms to store data:

  • sessionStorage: Stored data is preserved as long as the browser is open, including page reloads and restores.
  • localStorage: Data is preserved until it is cleared by the user or the application. It persists even if the browser is closed and reopened.

Both sessionStorage and localStorage allow you to store key-value pairs in the browser, and both provide the same set of functions to manage data.

For sessionStorage (example taken from MDN):

// Save data to sessionStorage
window.sessionStorage.setItem('key', 'value');

// Get saved data from sessionStorage
var data = window.sessionStorage.getItem('key');

// Remove saved data from sessionStorage
window.sessionStorage.removeItem('key');

// Remove all saved data from sessionStorage
window.sessionStorage.clear();

For localStorage:

// Save data to localStorage
window.localStorage.setItem('key', 'value');

// Get saved data from localStorage
var data = window.localStorage.getItem('key');

// Remove saved data from localStorage
window.localStorage.removeItem('key');

How to store redux state?

As you are already aware, Redux provides a createStore function which takes our root reducer and returns the application store.

The store object holds the entire application store, and provides a few methods including one to register a listener.

store.subscribe(listener) can be used to add a change listener to the store, which will get called every time the store gets updated.

We will add a listener to the store, which will save the application state to localStorage.

Try adding this in the file where you create your store using createStore:

/**
 * This function accepts the app state, and saves it to localStorage
 * @param state
 */
const saveState = (state) => {
    try {
        // Convert the state to a JSON string 
        const serialisedState = JSON.stringify(state);

        // Save the serialised state to localStorage against the key 'app_state'
        window.localStorage.setItem('app_state', serialisedState);
    } catch (err) {
        // Log errors here, or ignore
    }
};

/**
 * This is where you create the app store
 */
const store = createStore(rootReducer);

/**
 * Add a change listener to the store, and invoke our saveState function defined above.
 */
store.subscribe(() => {
    saveState(store.getState());
});

How to reload the stored data, and restore the application state when the app is initialised again?

When we create our app store using createStore, we have the option to pass an initial state to the store using the second parameter to the function.

When the application starts up, we will check the localStorage for any saved data. If we find it, we will send it as the second parameter to createStore.

This way, when the app finishes initialising, it will have the same state as it did before the page was refreshed or the browser was closed.

Try adding this in the file where you create your store using createStore:

/**
 * This function checks if the app state is saved in localStorage
 */
const loadState = () => {
    try {
        // Load the data saved in localStorage, against the key 'app_state'
        const serialisedState = window.localStorage.getItem('app_state');

        // Passing undefined to createStore will result in our app getting the default state
        // If no data is saved, return undefined
        if (!serialisedState) return undefined;

        // De-serialise the saved state, and return it.
        return JSON.parse(serialisedState);
    } catch (err) {
        // Return undefined if localStorage is not available, 
        // or data could not be de-serialised, 
        // or there was some other error
        return undefined;
    }
};

/**
 * This is where you create the app store
 */
const oldState = loadState();
const store = createStore(rootReducer, oldState);

That's it! Now, combine the last two blocks of code, and your application has the ability to maintain state across page refreshes, or even across browser restarts.

Hope this helps. Cheers! :)

like image 159
Shishir Avatar answered Jan 08 '23 05:01

Shishir