redux-persist_迁移状态时如何使用Redux Persist

redux-persist

Storage has always been an integral part of building apps. While building a webapp for our company, I needed a way to persist my states in storage which was reliable, easy to use, and configurable based on the requirements.

存储一直是构建应用程序不可或缺的一部分。 在为我们的公司构建Web应用程序时,我需要一种将状态保持在存储中的方法,该方法可靠,易于使用并且可以根据要求进行配置。

Thankfully this library was the answer to all my problems!

幸运的是,这个库是我所有问题的答案!

This article is based on a problem I faced while working on a project. Let us dive deep and understand how the library helped me solve it.

本文基于我在项目中遇到的问题。 让我们深入了解图书馆如何帮助我解决它。

If you haven’t already used redux-persist, then do read the docs, as they’re self-explanatory. If you want to know why you should use this library, go through this article — it is a great intro by the author himself!

如果您尚未使用redux-persist ,那么请阅读文档,因为它们是不言自明的。 如果您想知道为什么要使用该库,请阅读本文 -这是作者本人的精彩介绍!

问题 (Problem)

Let’s take an example where I wanted to persist a reducer in my localStorage:

让我们举个例子,我想在我的localStorage中保留一个reducer:

//Reducer
reducerA: {  
    engine: {    
        model: "F5AAA",    
        manufacturer: "Ferrari"  
    },  
    tyre: {    
        model: "T123",   
		manufacturer: "MRF",    
		owner: {      
            details: {        
                name: "Zack",        
				age: "26"            
            }    
        }  
    },  
	condition: "prime"
}
//View
class TestComponent extends React.Component {  
    render() {    
        const model = someStateOfReducerA.tyre.model    
        const manufacturer = someStateOfReducerA.tyre.manufacturer
        
		return (      
            <div>{model}</div>      
            <div>{manufacturer}</div>    
        )  
    }
}

//Reducer in localStorage
reducerA: {  
    engine: {    
        model: "F5AAA",    
		manufacturer: "Ferrari"  
    },  
	tyre: {    
        model: "T123",    
		manufacturer: "MRF",    
		owner: {      
            details: {        
                name: "Zack",        
				age: "26"            
            }    
        }  
    },  
	condition: "prime"
}

Now this reducer has persisted in our client’s device. So what will happen if I introduce a new key to our reducerA?

现在,该减速器已保留在我们客户的设备中。 那么,如果我为我们的reducerA引入新的密钥,将会发生什么?

reducerA: {  
	engine: {    
    	model: "F5AAA",    
	    manufacturer: "Ferrari"  
   	},  
    tyre: {    
    	model: "T123",    
        manufacturer: "MRF",    
        owner: {      
        	details: {        
            	name: "Zack",        
                age: "26",        
                address: "CA" // NEW KEY ADDED
			}    
		}  
	},  
    condition: "prime"
}

Let’s say we have a view which renders the value of our newly introduced key:

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

//View with new key address
class TestComponent extends React.Component {  
    render() {    
        const model = someStateOfReducerA.tyre.model    
        const manufacturer = someStateOfReducerA.tyre.manufacturer    
        const address = someStateOfReducerA.tyre.owner.details.address
        
		return (      
            <div>{model}</div>      
            <div>{manufacturer}</div>      
            <div>{address}</div>
		)  
    }
}

When I load my application with the newly introduced key, the rendering of our view fails. It throws an error where it states:

当我用新引入的密钥加载应用程序时,视图的呈现失败。 它在以下位置引发错误:

Cannot render address of undefined

This happened because the client’s storage is in sync with the rootReducer initialized during our app reload.

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

Even though we introduced the new key, the client’s storage never received it. It initializes our rootReducer with the old values in storage, where the address never existed, and causes the rendering of our component to fail.

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

(Solution)

This leads to a well-known concept: the migration of the database.

这导致了一个众所周知的概念:数据库的迁移。

A schema migration is performed on a database whenever it is necessary to update or revert that database’s schema to some newer or older version. Migrations are performed programmatically by using a schema migration tool — Wikipedia

每当需要将数据库的架构更新或还原到较新或较旧的版本时,就会对数据库执行架构迁移迁移是通过使用模式迁移工具进行编程- 维基百科

LocalStorage is in fact a small database of key value pairs. Redux Persist does it beautifully. If you look at a project initialized with this library, it already uses a default version -1. Take a look below at the screenshot taken from the application tab in the Chrome dev tool.

实际上,LocalStorage是键值对的小型数据库。 Redux Persist做得很漂亮。 如果查看使用此库初始化的项目,则该项目已使用默认版本-1 。 下面看一下从Chrome开发工具的“应用程序”标签中截取的屏幕截图。

This is really good! The library already maintains a default version for us, so that we can incorporate the migration feature in the future.

这真的很好! 该库已经为我们维护了一个默认版本,以便将来我们可以合并迁移功能。

The key is to configure your persist configuration in your rootReducer.

关键是在rootReducer中配置持久配置。

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

It is important that we update the version to 0, so that it migrates our storage from -1 to 0.

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

Next, we write the migration to let our storage know that there is an update.

接下来,我们编写迁移操作,以使我们的存储设备知道有更新。

const migrations = {  
    0: (state) => {    
        return {      ...
			state,      
			tyre: {        ...
				state.tyre,        
				owner: {          ...
					state.tyre.owner,          
					details: {
                        state.tyre.owner.details,
                        address: "CA" //New Key added for migration
                    }
				}      
			}    
		}  
    }
}

The migrations are then used in our persist config mentioned above:

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

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

Thus, when we reload our application, our application goes through a reconciliation phase where the storage is brought in sync with the newly-updated reducer.

因此,当我们重新加载应用程序时,我们的应用程序将进入协调阶段,在此阶段,存储将与新更新的reducer同步。

结论 (Conclusion)

The configuration above will always keep the application updated on the client side when you release new versions. It is very important that we are careful about this when making offline first apps.

当您发布新版本时,以上配置将始终在客户端上更新应用程序。 制作离线首批应用程序时,请务必谨慎,这一点非常重要。

It is simple once you understand the basic concept and technique to do it. I hope this article helped you understand the importance of managing versions of your states in storage :)

一旦您了解了执行此操作的基本概念和技术,它就很简单。 我希望本文能帮助您了解管理存储中状态版本的重要性:)

Follow me on twitter to get more updates regarding new articles and to stay updated in latest frontend developments. Also share this article on twitter to help others know about it. Sharing is caring ^_^.

推特上关注我,以获取有关新文章的更多更新,并随时了解最新的前端开发。 也可以在Twitter上分享此文章,以帮助其他人了解它。 分享是关怀^ _ ^。

一些有用的资源 (Some helpful resources)

  1. https://github.com/rt2zz/redux-persist/blob/master/docs/api.md

    https://github.com/rt2zz/redux-persist/blob/master/docs/api.md

  2. https://medium.com/@clrksanford/persist-ence-is-key-using-redux-persist-to-store-your-state-in-localstorage-ac6a000aee63

    https://medium.com/@clrksanford/persist-ence-is-key-using-redux-persist-to-store-your-state-in-localstorage-ac6a000aee63

  3. https://medium.com/async-la/redux-persist-your-state-7ad346c4dd07

    https://medium.com/async-la/redux-persist-your-state-7ad346c4dd07

翻译自: https://www.freecodecamp.org/news/how-to-use-redux-persist-when-migrating-your-states-a5dee16b5ead/

redux-persist

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue 3 的状态管理库 Pinia 和 Redux 的持久化库 redux-persist 的结合使用可以实现在 Vuex 中使用的持久化存储功能。 首先,安装依赖: ```shell npm install pinia redux-persist ``` 然后在 `src/store/index.ts` 中引入 Pinia 和 redux-persist: ```typescript import { createPinia } from 'pinia' import { persist } from 'pinia-plugin-persist' import { createStore } from 'redux' import { persistStore, persistReducer } from 'redux-persist' import storage from 'redux-persist/lib/storage' const pinia = createPinia() // 定义 Pinia 插件,使用 redux-persist 进行持久化存储 pinia.use( persist({ // 持久化存储的 key key: 'pinia', // 持久化存储的引擎,默认使用 localStorage storage, // 将 Pinia 的状态转换为 Redux状态 reducer: (state: any) => state.value, // 将 Redux状态转换为 Pinia 的状态 restoreState: (reduxState: any) => ({ value: reduxState }), }) ) // 定义 Redux 的 reducer const reducer = (state = 0, action: any) => { switch (action.type) { case 'INCREMENT': return state + 1 case 'DECREMENT': return state - 1 default: return state } } // 创建 Redux 的 store const store = createStore( persistReducer({ key: 'redux', storage }, reducer), undefined, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() ) // 持久化存储 Redux 的 store const persistor = persistStore(store) export { pinia, store, persistor } ``` Pinia 插件中使用 redux-persist 的 `persistReducer` 方法将 Pinia 的状态转换为 Redux状态,并进行持久化存储;`restoreState` 方法则将 Redux状态转换为 Pinia 的状态。 在应用中使用 Pinia ,可以直接使用 Pinia 的 API 进行状态管理,也可以通过 Redux 的 API 进行状态管理。例如,在 `src/App.vue` 中: ```vue <template> <div> <div>Pinia: {{ $pinia.state.value }}</div> <div>Redux: {{ $store.getState() }}</div> <button @click="$pinia.state.value++">Pinia +</button> <button @click="$pinia.state.value--">Pinia -</button> <button @click="$store.dispatch({ type: 'INCREMENT' })">Redux +</button> <button @click="$store.dispatch({ type: 'DECREMENT' })">Redux -</button> </div> </template> <script setup> import { useStore } from 'vuex' import { usePinia } from 'pinia' import { store, persistor } from './store' // 注册 Pinia 的 store const pinia = usePinia() pinia.useStore(store) // 注册 Redux 的 store const vuexStore = useStore() vuexStore.replaceState(persistor.getState()) store.subscribe(() => { vuexStore.replaceState(persistor.getState()) }) </script> ``` 在应用中同使用 Pinia 和 Redux ,需要注意 Pinia 和 Redux状态同步。在上面的例子中,Pinia 和 Redux状态都被持久化存储,因此在应用中重新加载,需要将 Redux状态从持久化存储中恢复,并将其转换为 Pinia 的状态。在 `script setup` 中,通过 `useStore` 获取 Vuex 的 store,并使用 `replaceState` 方法将 Redux状态设置为 Vuex 的状态;`store.subscribe` 方法监听 Redux状态变化,并在变化Redux状态设置为 Vuex 的状态。这样,在应用中使用 Pinia 的 API 进行状态管理,Pinia 和 Redux状态就是同步的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值