我正在构建一个通过 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>
);
}
快速猜测:这可能与
React.StrictMode
有关吗?
是否在应用程序中启用?你在使用 React 18 吗?在开发模式和生产模式下是否也会发生同样的情况?