为什么我的套接字会进入无限循环?

why does my socket goes into a infinite loop?

前端:

useEffect(() => {
    socketRef.current = io.connect("...", { transports : ['websocket'] })
    socketRef.current.emit("online", id)

    socketRef.current.on("message", ({ name, message }) => {
        setChat([ ...chat, { name, message , system: false } ])
    })

    socketRef.current.on("online", ( userID ) => {
        setChat([ ...chat, { name: userID , message: `has logged on` , system: true } ])
    })

    socketRef.current.on("offline", ( userID ) => {
        setChat([ ...chat, { name: userID , message: `${userID} has logged off` , system: true } ])
    })

    return () => {
        socketRef.current.disconnect()
    }
},[ chat ])

后端:

io.on('connection', socket => {
  socket.on('message', ({ name, message , userID }) => {
    io.emit('message', { name, message , userID })
  })

  socket.on('online', ( userID ) => {
    onlineApprovers.push({ user: userID , id: socket.id })

    console.log(userID + ' is online')
    io.emit('online', userID)
  })

  socket.on('disconnect', () => {
    console.log(onlineApprovers.find(a => a.id === socket.id).user + ' is offline')
    io.emit('offline', onlineApprovers.find(a => a.id === socket.id).user)
  })
})

我的代码所做的一些上下文: 当用户进入我的网站时,它会获取他们的用户 ID,发出 online 套接字事件,然后后端记录 userid is online,当他们离开我的网站时,套接字将断开连接,然后它将日志 userid is offline.

谁能告诉我为什么会进入死循环?当我登录时,它会一直记录 123 is online,然后记录 123 is offline,然后记录 123 is online,依此类推。它记录了当我什至没有关闭我的 window.

/编辑/

从我的代码中删除这些后:

// socketRef.current.on("online", ( userID ) => {
//  setChat([ ...chat, { name: userID , message: `has logged on` , system: true } ])
// })

// socketRef.current.on("offline", ( userID ) => {
//  setChat([ ...chat, { name: userID , message: `${userID} has logged off` , system: true } ])
// })       

它并没有进入无限循环,但是我的前端无法从我的后端接收数据。

当用户 joins/the chat 状态发生变化时,您将向服务器发出 online 事件,然后服务器通过发出 online 响应该事件事件发送到所有连接的客户端,这会导致执行以下侦听器:

socketRef.current.on("online", ( userID ) => {
  setChat([ ...chat, { name: userID , message: `has logged on` , system: true } ])
})

当你在这里调用 setChat() 并传递一个新数组时,这会导致你的反应组件重新渲染,从而使使用效果函数再次执行。然后,这会再次触发 online 事件,从而导致循环。

相反,您可以在组件挂载时创建套接字连接,方法是将 [] 作为对 useEffect() 的依赖项传递,并使用 setChat() 的状态更新函数来访问chat 的最新值:

useEffect(() => {
  socketRef.current = io.connect("...", { transports : ['websocket'] });
  socketRef.current.emit("online", id);

  socketRef.current.on("message", ({ name, message }) => {
    setChat(chat => [ ...chat, { name, message , system: false } ]);
  });

  socketRef.current.on("online", ( userID ) => {
    setChat(chat => [ ...chat, { name: userID , message: `has logged on` , system: true } ]);
  });

  socketRef.current.on("offline", ( userID ) => {
    setChat(chat => [ ...chat, { name: userID , message: `${userID} has logged off` , system: true } ]);
  });

  return () => {
    socketRef.current.disconnect();
  };

}, []);