在react中使用socket.io

275 阅读1分钟

socket.io 自动和手动连接服务

手动管理连接

客户端初始化

// src/utils/socket.ts
import { io } from 'socket.io-client';

export const socket = io('ws://localhost:3001', {
  autoConnect: false,
  // transports: ['websocket'],
  auth: (cb: (token: object) => void) => {
    cb({ token: localStorage.getItem('token') });
  },
});

参数介绍

  1. autoConnect默认为true。客户端立即打开与服务器的连接。设置false后,需要手动维护ws连接。
  2. auth 携带鉴权信息。服务端获取方式:client.handshake?.auth?.token

管理连接伪代码

  useEffect(() => {
    const onConnect = () => {
      console.log('connected');
      socket.volatile.emit('joinRoom', {
        chatroomId: chatroomId,
      });
    };

    const onConnectError = (err: any) => {
      console.log('error', err);
    };

    const onDisconnect = (reason: Socket.DisconnectReason) => {
      console.log('disconnect', reason);
    };

    socket.on('connect', onConnect);
    socket.on('connect_error', onConnectError);
    socket.on('disconnect', onDisconnect);
    socket.connect();
    return () => {
      socket.off('connect', onConnect);
      socket.off('connect_error', onConnectError);
      socket.off('disconnect', onDisconnect);
      socket.disconnect();
    };
  }, [chatroomId]);

ws自动连接

记录伪代码

注意事件要及时解绑

  const socketRef = useRef<Socket>(null);
  useEffect(() => {
    const socket = io('ws://localhost:3001', {
      auth(cb) {
        cb({
          token: localStorage.getItem('token'),
        });
      },
    });
    socketRef.current = socket;

    const onConnect = () => {
      console.log('connected');
      socket.volatile.emit('join_room', {
        chatroomId: chatroomId,
      });
    };
    const onConnectError = (err: any) => {
      console.log('error', err);
    };
    const onDisconnect = (reason: Socket.DisconnectReason) => {
      console.log('disconnect', reason);
    };

    const onMessage = (data: any) => {
      console.log(socket.id, 'socketId');
      console.log('message', data);
    };
    socket.on('connect', onConnect);
    socket.on('connect_error', onConnectError);
    socket.on('disconnect', onDisconnect);
    socket.on('message', onMessage);
    return () => {
      socket.off('connect', onConnect);
      socket.off('connect_error', onConnectError);
      socket.off('disconnect', onDisconnect);
      socket.off('message', onMessage);
      socket.disconnect();
    };
  }, [chatroomId]);

简易聊天室,前端代码

  1. 初始化socket
import { io } from 'socket.io-client';

export const socket = io('ws://localhost:3001', {
  autoConnect: false,
  // transports: ['websocket'],
  auth: (cb: (token: object) => void) => {
    cb({ token: localStorage.getItem('token') });
  },
});
  1. 切换room时,实现房间的进出。不完整代码如下
function ChatRoom({ chatroomId }: { chatroomId: number }) {
  const [chatList, setChatList] = useState<Message[]>([]);

  useEffect(() => {
    if (!chatroomId) return;
    socket.emit('join_room', { chatroomId }, ([res, error]: any) => {
      if (error) {
        console.log('join room error', error);
        return;
      }
      console.log('join room', res);
    });

    return () => {
      socket.emit('leave_room', { chatroomId });
    };
  }, [chatroomId]);

  useEffect(() => {
    const onMessage = (data: any) => {
      console.log('message', data);
      setChatList((prev) => {
        return [...prev, data];
      });
    };
    socket.on('message', onMessage);

    return () => {
      socket.off('message', onMessage);
    };
  }, []);
  return (
    <div className="pl-5 pt-10">
      some things
    </div>
  );
}

参考

  1. How to use with React
  2. nest-chat-room