使用跨不同组件的自定义钩子响应、更新和检测localStorage更改



我有一个自定义钩子来管理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是需要的,因为我们也需要监听同一文档中的变化。

最新更新