React App 在 useEffect 清理函数中未调用 WebSocket.close() 函数时崩溃

问题描述 投票:0回答:1

我正在构建一个通过 WebSocket 连接到服务器的测试应用程序。当我不使用 useEffect 钩子cleanup 部分中的 WebSocket.close() 函数时,应用程序崩溃。当包含 WebSocket.close() 时,该应用程序工作正常,ofc 我知道我应该在使用它后关闭连接/清理,但错误引用了某种“对象”? (下面列出了错误)。为什么会出现这种情况?

我试图理解这个问题,我想知道它是否与后台发生的事情有关。据我所知,清理发生在渲染之后,因此它不应该直接影响组件渲染之前的渲染或状态。我的理解正确吗,还是我遗漏了什么?

Uncaught runtime errors: ERROR An attempt was made to use an object that is not, or is no longer, usable ./src/CommunicationComponent.jsx/WebSocketComponent/
</socketRef.current.onopen@http://localhost:3000/static/js/bundle.js:191:27 EventHandlerNonNull*./src/CommunicationComponent.jsx/WebSocketComponent/<@http://localhost:3000/static/js/bundle.js:189:7 commitHookEffectListMount@http://localhost:3000/static/js/bundle.js:26115:30
  commitPassiveMountOnFiber@http://localhost:3000/static/js/bundle.js:27608:42 commitPassiveMountEffects_complete@http://localhost:3000/static/js/bundle.js:27580:38 commitPassiveMountEffects_begin@http://localhost:3000/static/js/bundle.js:27570:45 commitPassiveMountEffects@http://localhost:3000/static/js/bundle.js:27560:38
  flushPassiveEffectsImpl@http://localhost:3000/static/js/bundle.js:29443:32 flushPassiveEffects@http://localhost:3000/static/js/bundle.js:29396:18 ./node_modules/react-dom/cjs/react-dom.development.js/commitRootImpl/<@http://localhost:3000/static/js/bundle.js:29211:13
  workLoop@http://localhost:3000/static/js/bundle.js:36363:46 flushWork@http://localhost:3000/static/js/bundle.js:36341:18 performWorkUntilDeadline@http://localhost:3000/static/js/bundle.js:36578:25 EventHandlerNonNull*./node_modules/scheduler/cjs/scheduler.development.js/<@http://localhost:3000/static/js/bundle.js:36614:7
  ./node_modules/scheduler/cjs/scheduler.development.js@http://localhost:3000/static/js/bundle.js:36664:5 options.factory@http://localhost:3000/static/js/bundle.js:41901:31 __webpack_require__@http://localhost:3000/static/js/bundle.js:41331:32 fn@http://localhost:3000/static/js/bundle.js:41560:21
  ./node_modules/scheduler/index.js@http://localhost:3000/static/js/bundle.js:36679:20 options.factory@http://localhost:3000/static/js/bundle.js:41901:31 __webpack_require__@http://localhost:3000/static/js/bundle.js:41331:32 fn@http://localhost:3000/static/js/bundle.js:41560:21
  ./node_modules/react-dom/cjs/react-dom.development.js/<@http://localhost:3000/static/js/bundle.js:6083:40 ./node_modules/react-dom/cjs/react-dom.development.js@http://localhost:3000/static/js/bundle.js:31842:5 options.factory@http://localhost:3000/static/js/bundle.js:41901:31
  __webpack_require__@http://localhost:3000/static/js/bundle.js:41331:32 fn@http://localhost:3000/static/js/bundle.js:41560:21 ./node_modules/react-dom/index.js@http://localhost:3000/static/js/bundle.js:31913:20 options.factory@http://localhost:3000/static/js/bundle.js:41901:31
  __webpack_require__@http://localhost:3000/static/js/bundle.js:41331:32 fn@http://localhost:3000/static/js/bundle.js:41560:21 ./node_modules/react-dom/client.js@http://localhost:3000/static/js/bundle.js:31856:28 options.factory@http://localhost:3000/static/js/bundle.js:41901:31
  __webpack_require__@http://localhost:3000/static/js/bundle.js:41331:32 fn@http://localhost:3000/static/js/bundle.js:41560:21 ./src/index.js@http://localhost:3000/static/js/bundle.js:298:93 options.factory@http://localhost:3000/static/js/bundle.js:41901:31
  __webpack_require__@http://localhost:3000/static/js/bundle.js:41331:32 @http://localhost:3000/static/js/bundle.js:42544:56 @http://localhost:3000/static/js/bundle.js:42546:12

工作客户端代码:

import React, { useEffect, useRef } from 'react';

export default function WebSocketComponent({ children }) {
  const socketRef = useRef(null);
  const isEstablish = useRef(false);  // Tracks if the WebSocket connection is established
  const inputRef = useRef(null);  // Ref for the input field

  useEffect(() => {
    if(!isEstablish.current)
    {
        socketRef.current = new WebSocket('ws://localhost:8080');

        socketRef.current.onopen = () => {
        console.log('WebSocket connection established.');
        socketRef.current.send('Hello Server!');
        isEstablish.current = true;  // Mark connection as established
        };

        socketRef.current.onmessage = (event) => {
        console.log('Message from server:', event.data);
        };

        socketRef.current.onerror = (error) => {
        console.error('WebSocket error:', error);
        };

        socketRef.current.onclose = () => {
        console.log('WebSocket connection closed.');
        isEstablish.current = false;  // Mark connection as closed
        };
    }
    // Cleanup function 
    return () => {
      if (socketRef.current) {
        socketRef.current.close(); //it must be here, return a error in other case
        isEstablish.current = false;
      }
    };
  }, []); 

  // Function to send data to the server
  const sendToServer = () => {

    if (isEstablish.current && socketRef.current.readyState === WebSocket.OPEN) {
      const message = inputRef.current.value;
      console.log('Sent to server:', message);
      socketRef.current.send(message);  // Send message only if connection is open
    } else {
      console.error('WebSocket is not open. Cannot send message.');
    }
  };

  return (
    <div>
      <h1>WebSocket Example</h1>
      <input ref={inputRef} />
      <button onClick={sendToServer}>Send</button>
    </div>
  );
}
javascript reactjs websocket client
1个回答
0
投票

快速猜测:这可能与

React.StrictMode
有关吗? 是否在应用程序中启用?你在使用 React 18 吗?在开发模式和生产模式下是否也会发生同样的情况?

© www.soinside.com 2019 - 2024. All rights reserved.