You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 17:33:31