React中SignalR消息处理函数无法获取最新组件状态问题
React + SignalR 回调无法获取最新组件状态的问题解决
这是闭包陷阱导致的问题:你的connect函数在组件首次挂载时(useEffect空依赖)执行,此时connection.on注册的ReceiveMyMessage回调捕获了当时的counter初始值(0)。后续counter更新触发组件重渲染时,这个回调函数仍引用着第一次渲染时的闭包,所以始终打印旧值。
解决方案:用useRef保存最新状态值
useRef的.current属性是可变的,不会触发组件重渲染,且能在闭包中始终拿到最新值,是解决这类问题的最优方案。
修改后的代码示例:
import { useState, useEffect, useRef } from 'react'; import { HubConnectionBuilder, LogLevel, HubConnection } from '@microsoft/signalr'; const YourComponent = () => { const [counter, setCounter] = useState(0); const [connection, setConnection] = useState<HubConnection>(); // 用useRef保存最新的counter值 const counterRef = useRef(counter); // 每次counter更新时同步到ref useEffect(() => { counterRef.current = counter; }, [counter]); const MyLog = (message: string) => { console.log(message); // 访问ref的current属性获取最新值 console.log(counterRef.current); }; useEffect(() => { const connect = async (): Promise<void> => { const connectionInstance = new HubConnectionBuilder() .withUrl(import.meta.env.VITE_SIGNALR) .configureLogging(LogLevel.Information) .build(); connectionInstance.on("ReceiveMyMessage", (message) => { MyLog(message); }); await connectionInstance.start(); setConnection(connectionInstance); }; connect(); // 组件卸载时关闭连接,避免内存泄漏 return async () => { if (connection) { await connection.stop(); } }; }, []); // 递增counter的按钮事件 const incrementCounter = () => { setCounter(prev => prev + 1); }; return ( <div> <p>当前计数:{counter}</p> <button onClick={incrementCounter}>计数+1</button> </div> ); }; export default YourComponent;
原理说明
counterRef.current会在counter状态更新时同步最新值,不受闭包的限制。- SignalR的回调函数中访问
counterRef.current,每次触发时都能拿到组件的最新状态值。
内容的提问来源于stack exchange,提问作者beseus
相关产品推荐
相关产品推荐

