NestJS Socket.Io покинул комнату, но все еще получает сообщения

У меня три комнаты General, TypeScript и Nest. Я присоединяюсь к общей комнате на первой и второй вкладке браузера. Когда я решаю покинуть «Общие» со второй вкладки и присоединиться к комнате TypeScript, я все равно получаю сообщения от «Общих», хотя должен был покинуть ее. Ошибка возникает, когда вы переключаетесь в комнату, которая использовалась другим клиентом, и покидаете ее. Я использую NodeJs, Socket.io, NestJS и React.

Сервер

@WebSocketGateway()
 export class ChatGateway implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect {
 
  @WebSocketServer() server: Server;
  private logger: Logger = new Logger('ChatGateway');
 
  @SubscribeMessage('msgToServer')
  handleMessage(client: Socket, message: { sender: string, room: string, message: string }): void {
    
   this.server.to(message.room).emit('msgToClient',  message);
   this.logger.log(`msgToClient: ${message}`);
   

   
  }
  @SubscribeMessage('joinRoom')
  handleRoomJoin(client: Socket, room: string ) {
    client.join(room);
    client.emit('joinedRoom', room);
    this.logger.log(`Client joined ${room}`);
  }

  afterInit(server: Server) {
   this.logger.log('Init');
  }
 
  handleDisconnect(client: Socket) {
   this.logger.log(`Client disconnected: ${client.id}`);
  }
 
  handleConnection(client: Socket, ...args: any[]) {
   this.logger.log(`Client connected: ${client.id}`);
  }
  @SubscribeMessage('leaveRoom')
  handleRoomLeave(client: Socket, room: string ) {
    console.log(client.id);
   /*  console.log(client.rooms);
    console.log(client.adapter.rooms); */
    client.leave(room);
  /*   console.log(room); */
  /*   client.rooms = {};
    delete client.adapter.rooms[room]; */
    client.emit('leftRoom', room);
    this.logger.log(`Client left ${room}`);
  /*   console.log(client.adapter.rooms);
    console.log(client.rooms); */
   // console.log(client.adapter.rooms) 
    
  }
 }

Клиент

  const [state, setState] = useState({ sender: "", room: "", message: "" });
  const [chat, setChat] = useState([
    { sender: "Peter", room: "General", message: "test" },
  ]);
  const socket = io(BASE_URL);
  const [room, setRoom] = useState({
    General: false,
    TypeScript: false,
    NestJS: false,
  });
  console.log(room);
  useEffect(() => {
    socket.on("msgToClient", (msg) => {
      setChat([...chat, { ...msg }]);
    });
  });

  const onTextChange = (e) => {
    setState({ ...state, [e.target.name]: e.target.value });
  };

  const onMessageSubmit = (e) => {
    e.preventDefault();
    const { sender, room, message } = state;
    socket.emit("msgToServer", { sender, room, message });
    setState({ message: "", sender: "", room: "" });
  };

  const toggleRoomMembership = (chatroom) => {
    const isMemberOfActiveRoom = (chatroom) => {
      return room[chatroom];
    };
    if (isMemberOfActiveRoom(chatroom)) {
      setRoom({ ...room, [chatroom]: false });
    
      socket.emit("leaveRoom", chatroom);
    } else {
      setRoom({ ...room, [chatroom]: true });

      socket.emit("joinRoom", chatroom);
    }
  };

  const renderChat = () => {
    return chat.map(({ sender, message }, index) => (
      <div key={index}>
        <h3>
          {sender}: <span>{message}</span>
        </h3>
      </div>
    ));
  };

person retro    schedule 08.09.2020    source источник


Ответы (1)


Оказывается решение простое. Поместите сокет в useEffect и создайте для него состояние.

const [socket, setSocket] = useState({});
     useEffect(() => {
    const socket = io(BASE_URL);
    setSocket(socket);
    socket.on("msgToClient", (msg) => {
      setChat([...chat, { ...msg }]);
     
    });
    
  }, []);
person retro    schedule 09.09.2020