zl程序教程

您现在的位置是:首页 >  其它

当前栏目

[Redux] Persisting the State to the Local Storage

to The State local redux Storage
2023-09-14 08:59:19 时间

We will learn how to use store.subscribe() to efficiently persist some of the app’s state to localStorage and restore it after a refresh.

 

To save data in to localStroge,  we first create a localStorgejs file and two methods, one for get and one for set:

export const loadState =  () => {
    // Important to use try catch for localStorage if browser doesn't support local storge
    try{
        const serializedState = localStorage.getItem('state');
        if(serializedState === null){
            // if there is no item stored, then use default ES6 param
            return undefined;
        }else{
            return JSON.parse(serializedState)
        }
    }catch(err){
        return undefined;
    }
}


export const saveState = (state) => {
    try{
        const serializedState = JSON.stringify(state);
        localStorage.setItem('state', serializedState);
    }catch(err){
        console.error("Cannot save to storage");
    }
}

The data we want to save into localStorage should be serializable. And should use try and catch to handle error.

 

Use loadState() to get presisted data and to create store:

const persistedState = loadState();
const store = createStore(todoApp, persistedState);

 

Subscribe to the store, everytime there is something changed, save the todos into localStorge:

store.subscribe( () => {
  const {todos} = store.getState();
  saveState({
    todos
  })
})

 

If already save some todos into the localStroge and refresh the app, then we find that we cannot save any todo anymore. this is because in the application we use 'nextTodoId':

let nextTodoId = 0;
export const addTodo = (text) => ({
    type: 'ADD_TODO',
    id: (nextTodoId++).toString(),
    text,
});

Everytime page refresh it will start from zero again, then it cause the problem.

 

Install:

npm i --save node-uuid

node-uuid has a method call v4() to generate a random id:

// Generate a v4 (random) id 
uuid.v4(); // -> '110ec58a-a0f2-4ac4-8393-c866d813b8d1' 

We can use it to replace the old implemention:

import {v4} from 'node-uuid';

export const addTodo = (text) => ({
    type: 'ADD_TODO',
    id: v4(),
    text,
});

 

One thing to be improved is everytime we update the stroe, saveState() function will be invoked. We want to add throttle to it:

Install:

npm i --save lodash
import throttle from 'lodash/throttle';

const persistedState = loadState();
const store = createStore(todoApp, persistedState);


store.subscribe( throttle(() => {
  const {todos} = store.getState();
  saveState({
    todos
  })
}, 1000));

 

------------------------------

If look at the tests for createStore(), the second args can accpet 'undefined', [], {}, fn but NOT null. So it is important to return 'undefined' let reducer accept the ES6 default param. 

See Link: https://github.com/reactjs/redux/blob/master/test/createStore.spec.js#L546