admin管理员组文章数量:1022804
I have a custom hook to manage localStorage
like below:
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];
}
This custom hook is declared to use the same localstorage key for two or more ponents in one screen. e,g.
const [state, setState] = useLocalStorage('key', false);
At this time, since ponents using useLocalStorage
want to work according to the state change of localStorage
, we try to use the state returned by useLocalStorage
as the second parameter of useEffect
.
useEffect(() => {
foobar()
}, [state]);
I expected the foobar()
function in useEffect
to work when the "state" changes in all ponents that declared this useEffect
. However, foobar()
only worked for one ponent out of several ponents using this same useEffect
.Why this is happening? How do I get it to work the way I want it to?
I have a custom hook to manage localStorage
like below:
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];
}
This custom hook is declared to use the same localstorage key for two or more ponents in one screen. e,g.
const [state, setState] = useLocalStorage('key', false);
At this time, since ponents using useLocalStorage
want to work according to the state change of localStorage
, we try to use the state returned by useLocalStorage
as the second parameter of useEffect
.
useEffect(() => {
foobar()
}, [state]);
I expected the foobar()
function in useEffect
to work when the "state" changes in all ponents that declared this useEffect
. However, foobar()
only worked for one ponent out of several ponents using this same useEffect
.Why this is happening? How do I get it to work the way I want it to?
1 Answer
Reset to default 6You should set up an event listener for storage changes in order to have the updated value. See the code below and the note about storage event:
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];
}
You might wonder why this dispatchEvent
is used. Well here is what MDN says about storage event:
The
storage
event of theWindow
interface fires when a storage area (localStorage
) has been modified in the context ofanother document
.
This dispatchEvent
is needed as we need to listen to changes in the same document as well.
I have a custom hook to manage localStorage
like below:
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];
}
This custom hook is declared to use the same localstorage key for two or more ponents in one screen. e,g.
const [state, setState] = useLocalStorage('key', false);
At this time, since ponents using useLocalStorage
want to work according to the state change of localStorage
, we try to use the state returned by useLocalStorage
as the second parameter of useEffect
.
useEffect(() => {
foobar()
}, [state]);
I expected the foobar()
function in useEffect
to work when the "state" changes in all ponents that declared this useEffect
. However, foobar()
only worked for one ponent out of several ponents using this same useEffect
.Why this is happening? How do I get it to work the way I want it to?
I have a custom hook to manage localStorage
like below:
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];
}
This custom hook is declared to use the same localstorage key for two or more ponents in one screen. e,g.
const [state, setState] = useLocalStorage('key', false);
At this time, since ponents using useLocalStorage
want to work according to the state change of localStorage
, we try to use the state returned by useLocalStorage
as the second parameter of useEffect
.
useEffect(() => {
foobar()
}, [state]);
I expected the foobar()
function in useEffect
to work when the "state" changes in all ponents that declared this useEffect
. However, foobar()
only worked for one ponent out of several ponents using this same useEffect
.Why this is happening? How do I get it to work the way I want it to?
1 Answer
Reset to default 6You should set up an event listener for storage changes in order to have the updated value. See the code below and the note about storage event:
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];
}
You might wonder why this dispatchEvent
is used. Well here is what MDN says about storage event:
The
storage
event of theWindow
interface fires when a storage area (localStorage
) has been modified in the context ofanother document
.
This dispatchEvent
is needed as we need to listen to changes in the same document as well.
本文标签:
版权声明:本文标题:javascript - React, update and detect localStorage changes with a custom hook across different components - Stack Overflow 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://it.en369.cn/questions/1745575206a2156977.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论