React中useState存储SocketIO实例后读取id属性始终为undefined问题
问题原因
socket.io 客户端调用io()初始化实例时,会立即返回实例对象,但和服务端的 WebSocket 连接是异步建立的,id属性只有在连接成功(connect事件触发)之后才会被正式赋值。你在state更新后立即读取id的时间点,连接还未完成,因此返回undefined。
你直接打印完整socket实例能看到id,是因为浏览器控制台打印引用类型对象时,读取的是你点开查看时刻的对象值,此时连接已经建立完成,和代码执行时的实际值有时间差。
解决方案
监听socket实例的connect事件,在连接成功的回调中读取id即可:
useEffect(() => { if (!socketio) return; const handleConnect = () => { console.log("socket id " + socketio.id); // 所有需要用到socket id的业务逻辑都可以放在此处执行 }; // 绑定连接成功事件 socketio.on('connect', handleConnect); // 组件卸载时解绑事件,避免内存泄漏 return () => { socketio.off('connect', handleConnect); }; }, [socketio]);
优化建议
socket实例不需要响应式变化触发组件重渲染,用useRef存储比useState更合适,可避免不必要的重渲染开销:
import { useRef, useEffect } from 'react'; import io from 'socket.io-client'; const YourComponent = () => { const socketRef = useRef(null); useEffect(() => { // 初始化socket const socketInstance = io("http://localhost:8700/"); socketRef.current = socketInstance; // 监听连接成功 const handleConnect = () => { console.log("socket id " + socketRef.current.id); }; socketInstance.on('connect', handleConnect); // 组件卸载清理逻辑 return () => { socketInstance.off('connect', handleConnect); socketInstance.disconnect(); }; }, []); // 其他业务逻辑 return <div></div>; };
内容的提问来源于stack exchange,提问作者Novajik
相关产品推荐
相关产品推荐

