[英]React hooks change the state on postMessage
I have a component with some state using useState
. 我有一个使用
useState
某种状态的组件。
This component opens a new tab and should receive a message event on postMessage. 该组件将打开一个新选项卡,并且应该在postMessage上收到消息事件。 For some reason, after I get the event, the state returns to its initial state.
由于某种原因,在我收到事件后,状态将返回其初始状态。
I tried saving the state to localStorage and it worked. 我尝试将状态保存到localStorage并成功。
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
const App = () => {
const [state, setState] = useState("hello");
const onClick = () => {
setState("world");
window.open("tab.html");
};
const onMessageReceivedFromIframe = event => {
console.log("onMessageReceivedFromIframe", state, event);
};
const addIframeListener = () =>
window.addEventListener("message", onMessageReceivedFromIframe);
const removeIframeListener = () =>
window.removeEventListener("message", onMessageReceivedFromIframe);
useEffect(() => {
addIframeListener();
return () => {
removeIframeListener();
};
}, []);
useEffect(() => {
console.log("Current state: ", state);
}, [state]);
return <button onClick={onClick}>Click here</button>;
};
ReactDOM.render(<App />, document.getElementById("app"));
<html>
<body>
tab
<script>
setTimeout(() => {
console.log("post");
window.opener.postMessage("some message", "https://9jzj7.csb.app");
window.close();
}, 2000);
</script>
</body>
</html>
The state returns to its initial state. 状态返回到其初始状态。
A demo can be seen here: https://codesandbox.io/s/trusting-waterfall-9jzj7 可以在此处查看演示: https : //codesandbox.io/s/trusting-waterfall-9jzj7
BTW: I know that the event is not fired from tab.html
but there is still an event that fires on tab opening. 顺便说一句:我知道没有从
tab.html
触发该事件,但是仍有一个事件在打开选项卡时触发。
seems your problem was with the deps array of your effect hook, and onMessageReceivedFromIframe
being created on every render. 似乎您的问题出在效果钩子的deps数组上,并且在每个渲染器上都创建了
onMessageReceivedFromIframe
。 the solution below should work like you expect. 以下解决方案应能按预期工作。 here is a link to the codesandbox
这是codesandbox的链接
const App = () => {
const [state, setState] = useState("hello");
const onClick = () => {
setState("world");
console.log(state);
window.open("tab.html");
};
const onMessageReceivedFromIframe = React.useCallback(
event => {
console.log("onMessageReceivedFromIframe", state, event);
},
[state]
);
useEffect(() => {
window.addEventListener("message", onMessageReceivedFromIframe);
return () =>
window.removeEventListener("message", onMessageReceivedFromIframe);
}, [onMessageReceivedFromIframe]);
React.useEffect(() => {
console.log("state", state);
}, [state]);
return <button onClick={onClick}>Click here</button>;
};
The problem is with the below code 问题是下面的代码
useEffect(() => {
addIframeListener();
return () => {
removeIframeListener();
};
}, []);
Since its calling addIframeListener
and removeIframeListener
from inside effect
and the state state
is getting used inside it. 由于其从内部
effect
调用addIframeListener
和removeIframeListener
,因此在其中使用了状态state
。
Change the code as 将代码更改为
useEffect(() => {
addIframeListener();
return () => {
removeIframeListener();
};
}, [state]);
If there is any props getting used by framelistener
function, keep that in dependent array otherwise you will end up getting old props 如果
framelistener
函数使用了任何道具,请将其保留在依赖数组中,否则最终会得到旧的道具
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.