更新 LocalStorage 中持久化的 Redux 状态结构

687 阅读2分钟

原文链接 www.freecodecamp.org/news/how-to…

redux-persist migratioin example github.com/rt2zz/redux…

前言

我们在开发redux的时候,经常需要将redux的状态存在本地存储中,这时候就会碰到一个问题,当我们更改redux的状态结构时,本地存储中的状态并不会发生变化。

例子

举个例子,我想在我的 localStorage 中持久化一个 reducer:

reducerA: { 
    name:'peter',
    age:26,
}
//View
class TestComponent extends React.Component {  
    render() {    
        const name = someStateOfReducerA.name
        const age  = someStateOfReducerA.age
        
	return (      
            <div>{name}</div>  
            <div>{age}</div>  
        )  
    }
}

//Reducer in localStorage
reducerA: {  
    name:'peter',
    age:26,
}

现在这个reducer一直存在于我们客户的设备中。 那么如果我给我们的 reducerA 引入一个新的 key 会发生什么?

reducerA: {  
	name:'peter',
        age:26,
        role:'doc'
}

假设我们有一个视图来呈现我们新引入的键的值:

//View
class TestComponent extends React.Component {  
    render() {    
        const name = someStateOfReducerA.name
        const age  = someStateOfReducerA.age
        const role = someStateOfReducerA.role
        
	return (      
            <div>{name}</div>  
            <div>{age}</div>  
            <div>{role}</div>
        )  
    }
}

当使用新引入的密钥加载应用程序时,视图呈现失败。 它在它声明的地方抛出一个错误:

Cannot render role of undefined

发生这种情况是因为客户端的存储与我们的应用重新加载期间初始化的 rootReducer 同步。

即使我们引入了新密钥,客户端的存储也从未收到它。 它使用存储中的旧值初始化我们的 rootReducer,该地址从不存在,并导致我们的组件渲染失败。

解决方法

这时我们需要理解一个概念:数据库迁移。 数据库迁移是指每当需要将该数据库的模式更新或恢复到某个较新或较旧的版本时,都会在数据库上执行模式迁移。迁移是通过使用模式迁移工具以编程方式执行的。 LocalStorage 实际上是一个小型的键值对数据库。 如果查看使用redux-persist初始化的项目,它已经使用默认版本 -1。 你可以在dev tool里面看到这个信息。

捕获.PNG redux-persist已经为我们维护了一个默认版本,以便我们将来可以合并迁移功能。

关键是在你的 rootReducer 中配置你的持久化配置。

import { persistStore, persistReducer, createMigrate } from 'redux-persist'

export const persistConfig = {  
    key: 'root 
    version: 0, //New version 0, default or previous version -1  
    storage,   
    migrate: createMigrate(migrations, { debug: false})
}

const persistedReducer = persistReducer(persistConfig, Reducers)
export const store = createStore(persistedReducer, applyMiddleware(thunk))

重要的是我们将版本更新为 0,以便它将我们的存储从 -1 迁移到 0。

接下来,我们编写迁移以让我们的存储知道有更新。

const migrations = {  
    0: (state) => {    
        return {
        ...state,
        role:'doc'
    }
}

然后在我们上面提到的持久配置中使用迁移:

migrate: createMigrate(migrations, { debug: false })

因此,当我们重新加载我们的应用程序时,我们的应用程序会将存储与新更新的 reducer 同步。

总结

当你发新版本时,上述配置将始终在客户端更新应用程序。