ReactJS UseEffect内存泄漏错误-原因是什么?

时间:2020-03-31 10:36:49

标签: reactjs memory-leaks socket.io axios

这是我使用React Hooks的第一个项目。今天,我遇到了内存泄漏问题-我的应用程序给了我这个错误:

警告:无法在已卸载的组件上执行React状态更新。这是空操作,但它表明应用程序中发生内存泄漏。要修复,请取消使用useEffect清理功能中的所有订阅和异步任务。

我研究了一些解决方案。例如,我可以使用变量来跟踪组件的状态 isMounted

唯一的问题是,我不确定在哪里实现此目标。例如,我的一个组件中有3个UseEffect钩子。内存泄漏错误可归因于此特定组件。

使用效果1:

 useEffect(() => {
    socket.on("allLobbyClients", clients => {
      if (readyList.length == clients.length) {
        socket.emit("gameStarting", activeGamePin);
        socket.on("gameStartingMsg", data => {
          updateGameStarting(data);
        });
        setTimeout(() => {
          navigate("/game-draw", true);
        }, 5000);
      }
    });
  }, [readyList]);

使用效果2:

  useEffect(() => {
    socket.on("readyClientIndexes", indexes => {
      updateReadyList(indexes);
    });
  }, []);

使用效果3:

useEffect(() => {
    socket.emit("joinRoom", activeGamePin);
    socket.emit("getClientsForLobby", activeGamePin);
    socket.on("allLobbyClients", data => {
      //Gets the 'Client Index', which can be used to identify them in the <ol> when they specify they are ready to start the game.
      let clientName = window.localStorage.getItem("clientName");
      updateClientIndex(data.indexOf(clientName));
      let activePlayers = data.map((client, index) => (
        <li
          id={index}
          key={index}
          className={readyList.includes(index) ? "ready" : "unready"}
        >
          {client}
        </li>
      ));
      updateClientList(activePlayers);
    });
  }, [readyList]);

我还有一个使用Axios发出POST请求的功能。

  function playerIsReady() {
    let gamePin = activeGamePin;
    axios
      .post(`${backend}/newIndex`, {
        clientIndex: clientIndex,
        gamePin: gamePin
      })
      .then(response => {
        console.log(response.data);
      });
    setTimeout(() => {
      socket.emit("playerReady", gamePin);
    }, 2000);
    socket.on("readyClientIndexes", indexes => {
      updateReadyList(indexes);
      updateReadyBtn("invisible");
    });
  }

我的主要问题是:内存泄漏错误可能来自何处?它源自我的useEffect挂钩之一,还是源自Axios函数?一段时间以来,我第一次对解决方案感到完全无助。

任何回复都非常感谢-非常感谢!

P.S。我怀疑该错误与Axios功能有关,因为在我的应用程序组件中发生了内存泄漏错误,该错误不利用UseEffect挂钩。因此,我被卡住了!

2 个答案:

答案 0 :(得分:1)

我要说,您需要取消订阅socket。通常是通过useEffect清理功能(return () => {...}

完成的

更新

实施isMounted后,请在要设置状态异步的每个位置的前面添加条件检查:isMounted && setSomeState(..)

答案 1 :(得分:1)

在不运行代码的情况下,我可能会查看套接字正在执行的所有工作。您将它们设置为可以工作,但是在卸载组件后没有什么可以关闭它们的。考虑从可以从useEffect返回的函数中清理它们。