简体   繁体   中英

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 ). 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)

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 )

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. In your case, it is getting created on every re-render. Also you do not need 2 useEffects .

Put the creation of socket instance and merge your 2 useEffects into 1 and provide an empty array as dependency. With this, your useEffect is executed only once and not on every re-render.

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 . With useRef, you always get the same instance unless you mutate it.

create socket with 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();
    }

}, []);
...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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