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

Socket重复调用致会话列表UI重复更新问题求助

问题解决:实时消息重复显示后合并的问题

问题根源

  1. Socket事件重复绑定:receivePersonalMessage的useCallback依赖为空数组,但组件重渲染时该函数会重新创建,导致useEffect里的socket.on重复绑定,同一条消息触发两次回调。
  2. 状态操作不规范:直接引用listData进行修改(const contactList: any = listData)会污染原状态;当findIndex返回-1(会话不在当前列表)时,splice(-1,1)会错误删除列表最后一项。
  3. 重复更新状态:回调里先手动修改状态,又调用handleListMyContact拉取后端列表,两次状态更新导致界面先显示手动添加的消息,再被接口返回的列表覆盖。

修复方案

核心修改点

  • 用函数式状态更新处理列表,避免直接操作原状态数组
  • 修正Socket事件绑定逻辑,防止重复监听
  • 移除重复的状态更新操作,优先用实时状态更新保证体验,仅在页面焦点恢复时同步后端数据

修复后代码

// 获取会话列表:添加authToken依赖,确保token变化时重新请求
const handleListMyContact = useCallback(async () => {
    const data = await getConversation(authToken);
    if (data) {
      setListData(data.info);
    } else {
      console.log("loading data...");
    }
  }, [authToken]);

// 页面焦点恢复时同步会话列表
useEffect(() => {
    if (focus) {
      handleListMyContact();
    }
  }, [handleListMyContact, focus]);

// 接收实时消息:用函数式更新处理状态,避免引用污染
const receivePersonalMessage = useCallback((data: any) => {
    console.log("data from emit", data);
    setListData(prevList => {
      const newList = [...prevList];
      const targetIdx = newList.findIndex(item => item.conversation_id === data.conversation_id);
      
      // 若会话已存在,先移除原项
      if (targetIdx !== -1) {
        newList.splice(targetIdx, 1);
      }
      // 将新消息会话置顶
      newList.unshift(data);
      return newList;
    });
  }, []);

// Socket事件绑定:用局部变量保存回调,确保解绑与绑定的是同一个函数
useEffect(() => {
    const messageHandler = receivePersonalMessage;
    socket.on("new_conversation_message", messageHandler);

    return () => {
      socket.off("new_conversation_message", messageHandler);
    };
  }, [socket]);

修复说明

  1. 函数式状态更新:通过setListData(prevList => ...)直接基于上一次状态修改,避免直接引用原数组导致的状态污染问题。
  2. Socket事件绑定优化:将回调赋值给局部变量,确保每次解绑的是同一个函数,同时减少不必要的依赖项,防止重复绑定。
  3. 移除重复更新:手动更新状态已经能实时显示最新消息,不需要立即调用接口拉取,保留页面焦点时的同步逻辑即可,减少网络请求和界面抖动。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 08:05:37