首页 > 解决方案 > 从服务器响应到特定房间(Python后端)后,React socket.io-client 不会重新渲染组件

问题描述

我有一个使用 Flask-SocketIO 用 Python 编写的服务器后端。我正在利用它的房间功能进行私人对话。在加入房间事件时,服务器会触发以下函数,让前端知道将消息发送到特定用户的位置:

socketio.emit('room name response', {'roomName': room_name, 'recipient': recipient}, to=sid)

sid连接到套接字时仅为用户创建的私人房间在哪里。然后我想将这些信息以 React 状态保存在地图中,如下所示:

function ChatWindow({ username, token }) {
  const [responses, setResponses] = useState([]);
  const [roomsMap, setRoomsMap] = useState(new Map());
  const [currentRoom, setCurrentRoom] = useState("");
  const [messageValue, setMessageValue] = useState("");
  var socket = null;

  useEffect(() => {
    socket = socketIOClient(ENDPOINT);
  });

  useEffect(() => {
    socket.on("global response", (data) => {
      setResponses((responses) => [...responses, data]);
    });

    socket.on("room name response", (data) => {
      console.log(`joined ${data.roomName} with ${data.recipient}`);
      setCurrentRoom((currentRoom) => data.roomName);
      setRoomsMap((roomsMap) => roomsMap.set(data.recipient, data.roomName));
    });

    return () => socket.close();
  }, []);

  const sendMessage = () => {
    if (messageValue.length < 1) {
      return;
    }

    socket.emit("global message", {
      user_name: username,
      message: messageValue,
      timestamp: Date.now(),
    });
    setMessageValue("");
  };

  const joinRoom = (recipient) => {
    socket.emit("join", {
      token: token,
      username: username,
      recipient: recipient,
    });

    // setCurrentRoom(() => roomsMap.get(recipient));
  };

  const leaveRoom = (recipient) => {
    socket.emit("leave", {
      token: token,
      username: username,
      recipient: recipient,
    });
    
    const newRooms = roomsMap;
    newRooms.delete(recipient);
    console.log(`left room with ${recipient}`);
    newRooms.forEach((val, key) => console.log(`${val}:${key}`));
    setRoomsMap(newRooms);
  };

  const checkUser = (userToCheck) => {
    if (userToCheck === username) {
      return styles.chatFromUser;
    } else {
      return styles.chatToUser;
    }
  };

  return (...);
}

export default ChatWindow;

遗憾的是,React 不会对套接字发出的消息做出反应,即使它可以在开发人员工具的网络选项卡中看到。global response作品很好。当我将后端功能更改为:

socketio.emit('room name response', {'roomName': room_name, 'recipient': recipient})

React 突然按预期工作。我试图理解它为什么会发生,特别是当浏览器似乎看到如上所述的传入消息时,所以这很可能是我的错误编码或一些 React/Javascript 的东西。

感谢您提前提供任何帮助。

标签: javascriptpythonreactjssocket.ioflask-socketio

解决方案


问题是有时会多次创建套接字,因此 useEffect 当前正在侦听的套接字不一定是房间里的那个。所以我做了一个全局套接字来解决这个问题,现在整个事情都可以工作了。


推荐阅读