我有一个自定义钩子来管理localStorage
,如下所示:
import { useEffect, useState } from 'react'
export default function useLocalStorage(key, initValue) {
const [state, setState] = useState(() => {
const value = localStorage.getItem(key);
if (value !== null) {
return JSON.parse(value);
}
localStorage.setItem(key, JSON.stringify(initValue));
return initValue;
})
useEffect(() => {
localStorage.setItem(key, state);
}, [key, state])
return [state, setState];
}
这个自定义钩子被声明为对一个屏幕中的两个或多个组件使用相同的localstorage键。e, g。
const [state, setState] = useLocalStorage('key', false);
此时,由于使用useLocalStorage
的元件希望根据localStorage
的状态变化来工作,因此我们尝试使用useLocalStorage
返回的状态作为useEffect
的第二个参数。
useEffect(() => {
foobar()
}, [state]);
我期望useEffect
中的foobar()
函数在"状态"时工作。声明此useEffect
的所有组件的更改。然而,foobar()
只适用于使用相同useEffect
的几个组件中的一个组件。为什么会发生这种情况?我如何让它按我想要的方式工作?
您应该为存储更改设置一个事件侦听器,以便获得更新的值。请参阅下面的代码和关于存储事件的说明:
import { useEffect, useState } from 'react'
export default function useLocalStorage(key, initValue) {
const [state, setState] = useState(() => {
const value = localStorage.getItem(key);
if (value !== null) {
return JSON.parse(value);
}
localStorage.setItem(key, JSON.stringify(initValue));
window.dispatchEvent(new Event("storage"));
return initValue;
});
useEffect(() => {
localStorage.setItem(key, state);
window.dispatchEvent(new Event("storage"));
}, [key, state]);
useEffect(() => {
const listenStorageChange = () => {
setState(() => {
const value = localStorage.getItem(key);
if (value !== null) {
return JSON.parse(value);
}
localStorage.setItem(key, JSON.stringify(initValue));
window.dispatchEvent(new Event("storage"));
return initValue;
});
};
window.addEventListener("storage", listenStorageChange);
return () => window.removeEventListener("storage", listenStorageChange);
}, []);
return [state, setState];
}
您可能想知道为什么要使用这个dispatchEvent
。下面是MDN对存储事件的描述:
当存储区域(
localStorage
)在another document
的上下文中被修改时,Window
接口的storage
事件触发。
这个dispatchEvent
是需要的,因为我们也需要监听同一文档中的变化。