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

Next.js中WebSocket回调更新状态后UI需交互才响应的问题

问题解决:Supabase WebSocket回调中状态更新不触发UI即时刷新

问题原因

Supabase的WebSocket回调函数运行在React的更新上下文之外,调用setFormations更新状态后,React无法立即检测到变化并触发组件重渲染,只有用户交互(点击、输入等)触发React的更新机制时,才会同步最新状态。

解决方案

方案1:手动批处理状态更新

使用React的unstable_batchedUpdates将状态更新包裹,强制React将该更新纳入批处理流程,触发即时重渲染:

import { unstable_batchedUpdates } from 'react-dom';

channel
  .on("broadcast", { event: "cursor-pos" }, async ({ payload }) => {
    console.log(payload);
    unstable_batchedUpdates(() => {
      setFormations((formations) => {
        let newFormations = applyChangeset(formations, payload[0].changes);
        return newFormations;
      });
    });
  })

方案2:手动触发重渲染

创建一个专门用于触发更新的状态,在状态更新后手动调用它强制组件重渲染:

import { useState } from 'react';

// 组件内部定义
const [_, forceUpdate] = useState(0);

channel
  .on("broadcast", { event: "cursor-pos" }, async ({ payload }) => {
    console.log(payload);
    setFormations((formations) => {
      let newFormations = applyChangeset(formations, payload[0].changes);
      return newFormations;
    });
    // 手动触发重渲染
    forceUpdate(prev => prev + 1);
  })

方案3:在React生命周期内管理订阅

将订阅逻辑放到useEffect中,确保回调函数处于React的上下文环境里:

import { useEffect } from 'react';

// 组件内部
useEffect(() => {
  const handleBroadcast = async ({ payload }) => {
    console.log(payload);
    setFormations((formations) => {
      let newFormations = applyChangeset(formations, payload[0].changes);
      return newFormations;
    });
  };

  // 订阅频道
  channel.on("broadcast", { event: "cursor-pos" }, handleBroadcast);

  // 组件卸载时取消订阅,避免内存泄漏
  return () => {
    channel.off("broadcast", handleBroadcast);
  };
}, [channel, setFormations]);

内容的提问来源于stack exchange,提问作者Kishan Sripada

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 03:01:01