简体   繁体   English

React钩子更改postMessage的状态

[英]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并成功。

index.js index.js

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"));

tab.html tab.html

<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调用addIframeListenerremoveIframeListener ,因此在其中使用了状态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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM