我正在创建一个聊天应用程序,其中消息变量是来自另一个组件.我想要到过滤器这消息根据他们的房间id
所以我用useEffect在每次消息更新时更新roomMessage变量。消息变量更新了,但是roomMessage没有更新,新消息也没有显示在屏幕上。是filter()函数的问题还是什么?
export default function Chat_body() {
///messages has all the message data
let {userName,userID,messages} = useContext(AuthContext);
const {roomID} = useParams();
const [roomMessages,setRoomMessages] = useState(messages.filter((message) => message.room === parseInt(roomID)).reverse())
useEffect(() => {
setRoomMessages(messages.filter((message) => message.room === parseInt(roomID)).reverse())
console.log(roomMessages)
}, [roomID,messages]);
return (
<div className="chat_body">
{roomMessages.map((message)=>{
return(
{roomMessages.map((message)=>{
return(
<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>
)
})}
)
}
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'
});
var channel = pusher.subscribe('chat');
channel.bind('message', function(data) {
setMessages([...messages,data]);
console.log(messages)
});
return ()=>{
channel.unbind_all();
channel.unsubscribe();
}
},[messages])
如果我Mapmessage变量,所有的消息都会显示出来,更新的消息也会呈现出来,但是当我试图过滤它们时,新消息却不会显示出来!
4条答案
按热度按时间omvjsjqw1#
看起来问题出在你在useEffect钩子中更新roomMessages状态的方式上。当你调用setRoomMessages时,React不会立即更新状态,而是调度更新,并且出于性能原因,React会将多个更新一起批处理。这意味着当你在setRoomMessages之后立即调用
console.log(roomMessages)
时,你可能看不到roomMessages的更新值。若要解决此问题,您可以使用useEffect挂钩以及roomID和messages依赖项,以便在其中任何一个发生更改时更新roomMessages状态:
这将确保每当roomID或消息发生变化时,roomMessages总是更新为最新过滤的消息。
此外,请确保推送订阅中的消息状态被正确更新,而不是使用setMessages([... messages,data]),您应该使用函数更新语法来确保您正确更新状态:
这将确保您始终使用消息的最新值来更新状态。
更新
问题可能与您在useEffect挂接中更新roomMessages状态的方式有关。当您在React中更新状态时,更改可能不会立即反映在state变量中。相反,React会批处理状态更新并在稍后应用它们。这意味着如果您尝试在更新状态变量后立即访问它,则可能看不到更新后的值。
要确保使用roomMessages的更新值,可以使用setRoomMessages函数的回调版本。回调函数将接收当前状态值作为参数,因此可以使用它基于当前值更新状态。
下面是使用回调函数更新roomMessages的代码的更新版本:
在这段代码中,我们在useEffect钩子的setRoomMessages调用中添加了一个回调函数,该回调函数接收当前状态值作为参数(currentMessages),并使用该值基于当前值更新状态,这确保了在更新状态值时,我们始终拥有最新的状态值。
注意,我们还将filter和reverse调用移到了setRoomMessages调用之外,因为不需要在每次渲染时创建新的filtered数组,而是在useEffect钩子中创建一次filtered数组,并使用它来更新状态。
7rfyedvj2#
b1zrtrql3#
只需从Chat_body组件中删除useState和useEffect钩子,并直接从上下文中过滤messages(您还使用了两次map,这是不需要的)。
ttcibm8c4#
我想明白了,问题是useParams收到的roomID的数据类型和message.room不一样,所以,每次我用
message.room === roomID
的条件进行过滤时,它都没有返回true。我必须用“==”使它成为prevMessage.filter(message => message.room == parseInt(roomID).reverse())
才能工作。我非常抱歉给大家一个艰难的时间为这样愚蠢的错误,并感谢大家帮助我了。