trpc useSubscription无法获取React状态更新问题咨询
tRPC useSubscription onData无法获取最新组件状态的问题解决
这不是tRPC的Bug,是闭包陷阱导致的典型问题。
问题原因
组件初始化时,useSubscription的onData函数会捕获当前的state值(也就是初始值'initial')。当你调用setState更新状态后,组件会重新渲染,但tRPC的useSubscription默认不会重新创建订阅实例,因此旧的onData函数依然在生效——它引用的是初始化时的闭包环境,自然拿不到更新后的state。
解决方案
方案1:让useSubscription随状态变化重新订阅
给useSubscription添加依赖配置,当目标状态更新时,强制重新创建订阅,让新的onData函数捕获最新的状态:
function Component() { const [state, setState] = useState('initial') const triggerSocket = trpc.trigger.useMutation() trpc.socket.useSubscription( {}, { onData() { console.log(state) // 现在能获取最新状态值 }, // 指定依赖数组,state变化时重新订阅 deps: [state], refetchOnMount: true } ) return <button onClick={async () => { setState('updated') await triggerSocket.mutateAsync() }}>Click me</button> }
适用场景:如果你的订阅逻辑需要随state变化调整(比如订阅参数依赖state),这种方案更合适。
方案2:用useRef保存最新状态(避免频繁重新订阅)
如果不需要重新订阅WebSocket,只是想在onData中获取最新状态,可通过useRef同步状态,避开闭包陷阱:
function Component() { const [state, setState] = useState('initial') const stateRef = useRef(state) const triggerSocket = trpc.trigger.useMutation() // 每次state更新时,同步到ref的current属性 useEffect(() => { stateRef.current = state }, [state]) trpc.socket.useSubscription({ onData() { console.log(stateRef.current) // 始终获取最新状态值 } }) return <button onClick={async () => { setState('updated') await triggerSocket.mutateAsync() }}>Click me</button> }
适用场景:订阅逻辑固定,仅需在回调中读取最新状态,这种方案更高效,不会触发多余的WebSocket重连。
内容的提问来源于stack exchange,提问作者Gustavo Shigueo
相关产品推荐
相关产品推荐

