在编写React项目时, 可能会存储一些状态, 比如说主题之类的, 在跨页面时如果要保持同一种状态, 可以使用最简单,实用的localStorage来完成.
localStorage
localStorage提供了键值对来进行存储和访问, 其中键和值都是字符串,在这里我们主要使用两个方法:
getItem, 传入一个key参数, 返回一个对应的值, 如果不存在值则返回nullsetItem, 传入key和value两个参数, 会把value存储在key上
removeItem(删除制定的key对应的值)和clear(删除所有存储的指)这里用不到.
如果我们存储一个不是字符串的值, 要先使用JSON.stringify转换为字符串,获取到的值使用JSON.parse转换.
创建自定义hooks
现在我们来创建一个自定义的React Hooks函数, 自动将组件的状态保存到localStorage中,
创建一个useLocalStorageState函数, 函数有两个参数:
defaultValue, 获取key对应的值时为null, 使用默认参数localStorageKey, 存储值的key
const useLocalStorageState = (defaultValue, localStorageKey) => {}
从localStorage获取值
正如上面提到的, 从localStorage中获取值, 使用JSON.parse进行转换,然后使用useState将值存储在内存中.
const useLocalStorageState = (defaultValue, localStorageKey) => {
const [value, setValue] = useState(JSON.parse(localStorage.getItem(localStorageKey)));
}
但是这样还有问题, 我们获取的值可能为null,也可能是无效的,错误的JSON, 使用JSON.parse可能会有错误, 我们需要处理这些情况, 并返回默认值.修改一下代码:
const useLocalStorageState = (defaultValue, localStorageKey) => {
const [value, setValue] = useState(() => {
const itemValue = localStorage.getItem(localStorageKey);
if(itemValue === null) return defaultValue;
try{
return JSON.parse(itemValue);
}catch{
return defaultValue;
}
});
}
我们已经成功的获取了值, 现在我们需要在状态变化时, 更新localStorage中的值.
监听状态变化并更新localStorage中的值
每当value发生变化时,我们使用setItem, 传入localStorageKey和JSON.stringify转换后的值, 然后使用useEffect.
useEffect(() => {
localStorage.setItem(localStorageKey, JSON.stringify(value));
}, [value])
但是请注意, 这里会有一个性能问题,localStorage是同步操作,意味着它会阻塞主线程, 目前来看, 数据都比较简单可以忽略不计, 但是如果当你存储大量数据时, 它会是一个隐患. 我们需要采取一下办法来改良, 比如, 不在value变化的时候更新, 而是采用定时的更新. 这里不做演示.
包装Hooks
const useLocalStorageState = (defaultValue, localStorageKey) => {
const [value, setValue] = useState(() => {
const itemValue = localStorage.getItem(localStorageKey);
if(itemValue === null) return defaultValue;
try{
return JSON.parse(itemValue);
}catch{
return defaultValue;
}
});
useEffect(() => {
localStorage.setItem(localStorageKey, JSON.stringify(value));
}, [value]);
return [value, setValue];
}