Socket事件在react中重置状态数组



在服务器端,我有这个nodejs应用程序:

io.use((socket, next) => {
socket.name = socket.handshake.headers.name;
socket.room = socket.handshake.headers.room;
socket.user_id = socket.handshake.headers.user_id;
return next();
});
let all_sockets = [];
io.on("connection", (socket) => {
const ob = {
id: socket.id,
room: socket.room,
name: socket.name,
user_id: socket.user_id
};
all_sockets = all_sockets.filter(el => el.user_id !== socket.user_id);
all_sockets.push(ob);
socket.on("message", (data) => {
const recipients = all_sockets.filter(el => el.room === socket.room && el.id !== socket.id);
recipients.forEach(el => {
io.to(el.id).emit('private', data);
})
});
socket.on("disconnect", (reason) => {
all_sockets = all_sockets.filter(el => el.id !== socket.id);
});
});

在客户端我有这个组件:

const Chat = () => {
const { username } = useParams();
const socket_url = `http://localhost:4000/`;
const [socket, setSocket] = useState(null);
const [chatMessages, setChatMessages] = useState([]);
const sendMessage = () => {
const msg = messageRef.current.value;
const message_object = {from: username, data: msg};
setChatMessages([...chatMessages, message_object]);
socket.emit('message', msg);
messageRef.current.value = '';
}

const connect = async () => {
try {
const body = {username: username};
const response = await fetch(`http://localhost:4000/login`, body);
const data = await response.json();
const sck = io(socket_url, {
path: "/socket.io",
autoConnect: true,
extraHeaders: {
room: data.user.room,
user_id: data.user._id,
name: data.user.name
}
});
sck.on('private', function(msg) {
const message_object = {from: 'user', data: msg};
setChatMessages([...chatMessages, message_object]);
});
setSocket(sck);
}
catch(exception){
console.log("exception",exception);
}
}
useEffect(() => {
connect();
}, []);
const messageRef = useRef('');
return (
<div>
<div>
<div>
{
JSON.stringify(chatMessages)
}
</div>
<div>
<input ref={messageRef} type="text" placeholder="Enter message"/>
</div>
<div>
<button onClick={sendMessage} >Send</button>
</div>
</div>
</div>
)
}

我用user1打开一个浏览器窗口,用user2打开另一个浏览器窗口,我输入来自user1的3条消息:

one
two
three

user1在屏幕上看到:

[{"from":"user1","data":"one"},{"from":"user1","data":"two"},{"from":"user1","data":"three"}]    

然而,user2将一直看到"chatMessages"重置。在第三条消息之后,user2看到:

[{"from":"user","data":"three"}]

如果user1输入"four",那么user2将看到:

[{"from":"user","data":"four"}]

同样,当user2输入:"hello"时,user1将在屏幕上看到:

[{"from":"user","data":"hello"}]

为什么状态数组被重置?这只发生在接收到的函数内部:

sck.on('private', function(msg) {
const message_object = {from: 'user', data: msg};
setChatMessages([...chatMessages, message_object]);
});    

捕获chatMessages闭包。它总是保持相同的"值"它有一段时间是"on"。附件。尝试使用功能更新。(最好在两个地方,在sck.onsendMessage函数中使用它。)

setChatMessages(curr => [...curr, message_object]);

最新更新