基础功能
- 将
state
保存到 localStorage
中,实现本地持久化;
- 如果清空了值,也从
localStorage
中删除这条数据;
- 会自动处理序列化和反序列化的操作;
- 重新刷新页面后也能拿到之前的值;
- 同源多页面之间也能共享值,当其中一个页面的值发生了改变,不刷新其他页面下也能更新值。
具体实现代码
import { useState, useEffect } from "react";
const useLocalStorageState = (key, defaultState) => {
const [localState, setLocalState] = useState(defaultState);
const [showState, setShowState] = useState(defaultState);
// 刷新页面后能拿到值
useEffect(() => {
const value = localStorage.getItem(key);
if (!value) {
return;
}
setLocalState(value);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
// 同源页面监听改变实时刷新
useEffect(() => {
const storageFuction = function(e) {
const value = e.newValue
setLocalState(value)
}
window.addEventListener('storage', storageFuction)
return () => {
window.removeEventListener('storage', storageFuction)
}
// console.log(localStorage.getItem(key))
}, [])
useEffect(() => {
if (localState) {
if (typeof localState === "object") {
localStorage.setItem(key, JSON.stringify(localState));
} else {
localStorage.setItem(key, String(localState));
}
setShowState(localState)
return;
}
localStorage.removeItem(key);
setShowState(undefined)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [localState]);
return [showState, setLocalState];
};
export default useLocalStorageState;
demo
demo1
import useLocalStorageState from './hooks/useLocalStorageState'
function App() {
const [state,setState] = useLocalStorageState('test', [])
return (
<div className="App" style={{textAlign: 'center'}}>
<header className="App-header">
<p>
{ state }
</p>
<button onClick={() => setState([...state, 'A'])}>Push A</button>
<button onClick={() => setState(state.slice(0, state.length - 1))}>Pop A</button>
</header>
</div>
);
}
export default App;
demo2
import useLocalStorageState from './hooks/useLocalStorageState'
function App() {
const [state,setState] = useLocalStorageState('test', '')
return (
<div className="App" style={{textAlign: 'center'}}>
<header className="App-header">
<p>
{ state }
</p>
<input value={state || ''} onChange={(e) => setState(e.target.value)} />
</header>
</div>
);
}
export default App;