在服务器端,我有这个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被重置,所以在第三条消息之后,uer2看到:
[{"from":"user","data":"three"}]
如果用户1将输入“四”,则用户2将看到:
[{"from":"user","data":"four"}]
此外,当user2键入以下内容时:“hello”,则user1将在屏幕上看到:
[{"from":"user","data":"hello"}]
为什么状态数组会被重置?这只会在received函数内部发生:
sck.on('private', function(msg) {
const message_object = {from: 'user', data: msg};
setChatMessages([...chatMessages, message_object]);
});
1条答案
按热度按时间bxfogqkk1#
chatMessages
是闭包捕获的。它总是保持在“on”连接期间的相同“值”。尝试使用函数更新。(最好在两个地方都使用它,在sck.on
和sendMessage
函数中。)