reactjs 套接字事件正在重置react中的状态数组

6l7fqoea  于 2023-01-25  发布在  React
关注(0)|答案(1)|浏览(95)

在服务器端,我有这个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]);
});
bxfogqkk

bxfogqkk1#

chatMessages是闭包捕获的。它总是保持在“on”连接期间的相同“值”。尝试使用函数更新。(最好在两个地方都使用它,在sck.onsendMessage函数中。)

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

相关问题