大家好,我是前端西瓜哥。
最近做需求,需要将数据保存到 localStorage 里,在组件初始化的时候获取,然后修改该值的时候,要保存到本地的 localStorage 中。
倒是并不难。
function App() { const STORAGE_NAME = 'app_theme'; const defaultVal = '前端西瓜哥' const [value, setValue] = useState(() => { const storage = localStorage.getItem(STORAGE_NAME); return storage || defaultVal; }) const changeValue = (val) => { localStorage.setItem(STORAGE_NAME, val); setValue(val); } return ( <div> <input value={value} onChange={e => changeValue(e.target.value)}/> </div> ); }
很显然,这些逻辑完全可以封装为一个 React Hook,名字很容易想到为 useLocalStorageState。
const useLocalStorageState = (key, defaultValue) => { const data = localStorage.getItem(key); const [value, setValue] = useState(data || defaultValue); return [ value, (val) => { localStorage.setItem(key, val); setValue(val); } ]; };
逻辑并不复杂。就是在读和写的时候,加上 localStorage 的读写逻辑就好了。
用法如下:
function App() { const STORAGE_NAME = "app_theme"; const defaultVal = "前端西瓜哥"; const [value, setValue] = useLocalStorageState(STORAGE_NAME, defaultVal); return ( <div> <input value={value} onChange={e => setValue(e.target.value)} /> </div> ); }
其实这个实现还是比较粗糙的,只支持字符串格式,如果你要保存对象,需要自己手动 JSON.parse 和 JSON.stringify 来扩展了数据类型的范围。
我们可以加一下序列化和反序列化支持:
const useLocalStorageState = (key, defaultValue) => { const data = localStorage.getItem(key); const [value, setValue] = useState(JSON.parse(data || defaultValue)); return [ value, (val) => { localStorage.setItem(key, JSON.stringify(val)); setValue(val); } ]; }; // 使用 function App() { const STORAGE_NAME = "app_theme"; const defaultVal = { name: "前端西瓜哥" }; const [value, setValue] = useLocalStorageState(STORAGE_NAME, defaultVal); return ( <div> <input value={value.name} onChange={(e) => setValue({ name: e.target.value })} /> </div> ); }
另外,JSON 序列化和反序列方法如果不够用,我们可以再加个自定义序列反序列化方法:
const useLocalStorageState = (key, defaultValue, serializer, deserializer) => { defaultValue = localStorage.getItem(key) || defaultValue; const [value, setValue] = useState( deserializer ? deserializer(defaultValue) : JSON.parse(defaultValue) ); return [ value, (val) => { localStorage.setItem( key, serializer ? serializer(val) : JSON.stringify(val) ); setValue(val); } ]; };
其实优秀的第三方 React Hook 库 ahooks 也有这个实现,我还是建议大家用一些比较成熟的轮子,我这里只是提供一下思路。
ahooks 的 useLocalStorageState 的源码:
https://github.com/alibaba/hooks/blob/v3.4.0/packages/hooks/src/useLocalStorageState/index.ts
我是前端西瓜哥,喜欢写前端技术文章,欢迎关注我。