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

React聊天应用Filter()随变量更新失效问题及修复咨询

问题分析与解决

核心问题1:Context中消息更新的状态依赖错误

在context.js的Pusher监听回调里,你使用setMessages([...messages, data])更新状态,但这里的messages是闭包捕获的旧值,加上useEffect依赖了messages,每次消息更新都会重新创建Pusher连接,导致状态更新异常,新消息无法正确追加到列表。

核心问题2:Chat_body中冗余的状态同步与重复渲染

Chat_body里用useState和useEffect同步roomMessages完全没必要,不仅增加了状态同步的复杂度,还因为setState的异步特性,导致console.log无法获取最新值。另外代码里存在重复的roomMessages.map,会导致渲染错误。


修复代码

1. 修复context.js的消息更新逻辑

import React,{createContext,useState,useEffect} from 'react'
import jwt_decode from "jwt-decode";
import { useNavigate } from 'react-router-dom';
import pusherJs from 'pusher-js';

const endpointMessage = 'http://127.0.0.1:8000/message'
const [messages,setMessages] = useState([])

useEffect(()=>{
    const pusher = new pusherJs('f12d9df33bdc80d7947b', {
        cluster: 'ap2'
    });

    const channel = pusher.subscribe('chat');
    const handleMessage = (data) => {
        // 使用函数式更新,确保拿到最新的messages状态
        setMessages(prevMessages => [...prevMessages, data]);
    };
    channel.bind('message', handleMessage);

    return ()=>{
        channel.unbind('message', handleMessage); // 精准解绑指定回调
        channel.unsubscribe();
    }
}, []) // 移除messages依赖,只初始化一次Pusher连接

2. 简化Chat_body组件,移除冗余状态

export default function Chat_body() {
    const {userName,userID,messages} = useContext(AuthContext);
    const {roomID} = useParams();
    const roomIdNum = parseInt(roomID);

    // 用useMemo直接推导当前房间的消息,无需额外state
    const roomMessages = React.useMemo(() => {
        return messages
            .filter(message => message.room === roomIdNum)
            .reverse();
    }, [messages, roomIdNum]);
  
    return (
        <div className="chat_body">
            {roomMessages.map((message) => (
                <div 
                    key={message.id} 
                    className={userName === message.sender ? "chat_message recieved" : "chat_message"}
                >
                    <span className='avatar_span'><MdAccountCircle/></span>
                    <div className={userName === message.sender ? "message chat_recieved" : "message"}>
                        <span className='chat_name'>{message.sender}</span>
                        <div className={userName === message.sender ? "sent_message chat_reciever" : "sent_message"}>
                            <p>{message.message}</p>
                            <span className='timeSpan'>{message.sent_at}</span>
                        </div>
                    </div>
                </div>
            ))}
        </div>
    )
}

关键修复点说明

  • 函数式状态更新:Context中使用setMessages(prev => [...prev, data]),确保每次都基于最新的状态追加新消息,避免闭包陷阱。
  • 移除不必要的依赖:Context的useEffect不再依赖messages,只初始化一次Pusher连接,防止重复创建连接导致的异常。
  • 用useMemo替代状态同步:直接通过useMemo根据messages和roomID推导当前房间的消息,省去useState和useEffect的同步逻辑,避免异步更新问题。
  • 移除重复map:删除了Chat_body中重复的roomMessages.map,修复渲染错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 03:10:04