store 内容的持久化
对 store 内容的持久化一般是将其保存到 localStorage
里,这就要求所要保存的内容是可以被 JSON.stringify
序列化的。符合这个条件的话,就可以使用以下形式来定义一个可以自动将状态保存到 localStorage
的 store,并且支持状态的实时更新。
const state = proxy({
JSON.parse(localStorage.getItem('state')) || {
count: 0
},
});
subscribe(state, () => {
localStorage.setItem('state', JSON.stringify(state));
});
使用 valtio-persist
简化操作
为了简化持久化的操作,可以使用 valtio-persist
库来简化 store 的定义。在安装 valtio-persist
库之后,上面的示例可以简化为以下形式。
import { persist } from "valtio-persist";
interface State {
count: number;
}
const { store } = await persist<State>(
{
count: 0,
},
"state"
);
persist
函数所接受的第一个参数为这个 store 的初始状态,第二个参数为这个 store 保存到持久化存储的键名。在使用 persist
函数完成 store 的定义以后,这个 store 就可以像普通的 store 一样使用了。
如果需要将 store 的内容持久化到 localStorage
以外的地方,可以向 persist
函数提供第三个参数。这个参数接受一个对象,可以在其中使用 storageStrategy
来定义所要持久化的位置,例如 { storageStrategy: IndexedDbStrategy }
,就可以将 store 的内容持久化到 IndexedDB
中。在默认情况下,valtio-persist
会使用 localStorage
作为持久化存储的位置。
valtio-persist
中可以使用的持久化存储位置可以有以下选择,注意其中部分策略可能需要额外的依赖。
存储位置 | 策略名称 | 依赖 |
---|---|---|
localStorage | LocalStorageStrategy | valtio-persist |
sessionStorage | SessionStorageStrategy | valtio-persist |
IndexedDB | IndexedDbStrategy | valtio-persist/indexed-db |
Memory | MemoryStorageStrategy | valtio-persist |
除了可以配置存储位置以外,valtio-persist
还提供了 store 内容合并方法、条件持久化以及手动控制等功能。
在默认情况下,valtio-persist
采用浅比较的方式进行 store 内容的合并,这会跳过一些不能够序列化内容的检查,如果需要执行深比较合并,可以在 persist
的第三个参数中配置 { mergeStrategy: DeepMergeStrategy }
来完成切换。
在满足一定条件的情况下执行持久化的配置,是需要定义一个函数来进行判断的,这个函数可以通过第三个参数中的 shouldPersist
来传递给 persist
。
在 store 内容频繁更改的时候,可能需要减缓对持久化存储位置的操作 IO 压力,那么就可以使用 valtio-persist
提供的防抖功能来实现,这项功能可以在第三个参数中通过提供 debounceTime
的值来设定 valtio-persist
的防抖等待时间。
persist
函数返回的内容是一个对象,在之前的示例中只使用了其中的 store
属性,除了 store
属性以外,这个返回的对象里还有 persist
、restore
和 clear
三个方法。其中 persist
用于立刻将当前的状态持久化到指定的存储位置,restore
用于从指定的存储位置恢复状态,clear
用于清除指定的存储位置中的状态。这三个方法都是异步函数,在使用的时候注意要使用 await
关键字。