简体   繁体   English

谁能告诉我这个套接字事件有什么问题?

[英]Can anyone please tell me what's wrong this socket event?

I've emitted two events on user joined & left ( user_joined and user_left ).我在用户加入和离开时发出了两个事件( user_joineduser_left )。 It's working on the server-side but not working on the client-side.它在服务器端工作,但不在客户端工作。

Server-side code: (it's working, showing console.log on every connection)服务器端代码:(它正在工作,在每个连接上显示 console.log)

io.on('connection', function (socket) {
    const id = socket.id;

    /**
     * User Join Function
     */
    socket.on('join', function ({ name, room }) {
        const { user } = addUser({id, name, room}); // add user to users array
        socket.join(user.room);
        socket.emit('user_joined', users); // emit event with modified users array
        console.log(id, 'joined')
    })

    /**
     * User Disconnect function
     */
    socket.on('disconnect', () => {
        removeUser(id); // remove user form users array
        socket.emit('user_left', users);  // emit event with modified users array
        console.log(id, 'left')
    })


})

Client-side code: (Not firing on user_joined or user_left )客户端代码:(未在user_joineduser_left上触发)

const [players, setPlayers] = useState([]);

const ENDPOINT = 'localhost:5000';
socket = io(ENDPOINT);

useEffect(() => {
    const name = faker.name.firstName() + ' ' + faker.name.lastName();
    socket.emit('join', {name, room: 'global'}); // it's working fine

    return () => {
        socket.emit('disconnect');
        socket.off();
    }

}, [])

useEffect(() => {

    socket.on('user_joined', (users) => {
        setPlayers(users);
    }); // >>> Not Working <<<

    socket.on('user_left', (users) => {
        setPlayers(users);
    }); // >>> Not Working <<<

    console.log(socket) // it's working fine

}, [players]);

The socket instance needs to be created only once. socket实例只需要创建一次。 In your case, it is getting created on every re-render.在您的情况下,它会在每次重新渲染时创建。 Also you do not need 2 useEffects .您也不需要 2 个useEffects

Put the creation of socket instance and merge your 2 useEffects into 1 and provide an empty array as dependency.socket实例的创建并将您的 2 个useEffects合并为 1 并提供一个空数组作为依赖项。 With this, your useEffect is executed only once and not on every re-render.这样,您的 useEffect 只执行一次,而不是在每次重新渲染时执行。

Try this尝试这个

const [players, setPlayers] = useState([]);

useEffect(() => {
    const ENDPOINT = 'localhost:5000';
    socket = io(ENDPOINT);

    const name = faker.name.firstName() + ' ' + faker.name.lastName();
    socket.emit('join', {name, room: 'global'});

    socket.on('user_joined', (users) => {
        setPlayers(users);
    });

    socket.on('user_left', (users) => {
        setPlayers(users);
    });

    console.log(socket);

    return () => {
        socket.emit('disconnect');
        socket.off();
    }

}, []);
...

If you want to use the socket instance in other places of your component then make use of useRef .如果您想在组件的其他位置使用套接字实例,请使用useRef With useRef, you always get the same instance unless you mutate it.使用 useRef,除非您对其进行变异,否则您始终会获得相同的实例。

create socket with refs使用refs创建套接字

...
const [players, setPlayers] = useState([]);
const ENDPOINT = 'localhost:5000';

const socketInstance = useRef(io(ENDPOINT));// in react, with useRef, you always get the same instance unless you mutate it.
useEffect(() => {
    // socketInstance.current = io(ENDPOINT);

    const name = faker.name.firstName() + ' ' + faker.name.lastName();
    socketInstance.current.emit('join', {name, room: 'global'});

    socketInstance.current.on('user_joined', (users) => {
        setPlayers(users);
    });

    socketInstance.current.on('user_left', (users) => {
        setPlayers(users);
    });

    console.log(socketInstance.current);

    return () => {
        socketInstance.current.emit('disconnect');
        socketInstance.current.off();
    }

}, []);
...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM