aqteifan
aqteifan

Reputation: 504

emitting action with socketio into different react components

I am trying to emit a msg into different react components and update all components with new value.

server:

const express = require('express');
const socketio = require('socket.io');
const http = require('http');
const {addPlayer, removePlayer, getPlayer, getPlayerssInRoom, addRoom} = require('./players');
const cors = require('cors');

const PORT = process.env.PORT || 5000;

const router = require('./router');

const app = express();
const server = http.createServer(app);
const io = socketio(server);

app.use(cors());
app.use(router);
io.on('connection', (socket) => {
    socket.on('question', (question) => {
        socket.emit('setQuestion', question);
        socket.broadcast.to('rtd').emit('setQuestion', question);
        io.sockets.in('rtd').emit('setQuestion', question);
    });

    socket.on('disconnect', () => {
        console.log('User had left');
    });
});

app.use(router);

server.listen(PORT, () => console.log(`Server has started on port ${PORT}`));

First component where I emit an action to the server:

import React, {useEffect, useState} from 'react';
import Button from 'react-bootstrap/Button';
import io from 'socket.io-client';
let socket;

const Admin = () => {
    const [currentQuestion, setCurrentQuestion] = useState('');
    const ENDPOINT = 'localhost:5000';
    socket = io(ENDPOINT);

    const publishQuestion = () => {
        console.log('trying');
        socket.emit('question', currentQuestion);
    }
    
    useEffect(() => {
        socket = io(ENDPOINT);
        socket.on('connect', function (data) {
            console.log('socket: ', socket.id);
            socket.on('answer', (answer) => {
                console.log('do i get here');
            })
            socket.on('setQuestion', (newQuestion) => {
                setCurrentQuestion(newQuestion);
                console.log(newQuestion);

            })

        });
    }, [currentQuestion]);
    return (
        <div className="justify-content-center">
            <h1>Admin</h1>
            <input onChange={(event)=>setCurrentQuestion(event.target.value)}/>
            <Button onClick={()=> publishQuestion()}>Publish word</Button>
        </div>
    )
}

export default Admin;

Second component where I am having issue to listen to the emit that comes from the server:

import React, {useState} from 'react';
import io from 'socket.io-client';
let socket;

const Player = () => {
    const [currentQuestion, setCurrentQuestion] = useState('');
    const ENDPOINT = 'localhost:5000';
    socket = io(ENDPOINT);

    socket.on('connect', function (data) {
        console.log('socket: ', socket.id);
        socket.on('answer', (answer) => {
            console.log('do i get here');
        })
        socket.on('setQuestion', (newQuestion) => {
            setCurrentQuestion(newQuestion);
            console.log(newQuestion);

        })

    });
    return (
        <h1>player</h1>
    )
}

export default Player;

Anyone has an idea why the Player component not picking on the server emit (socket.on('setQuestion', (newQuestion))?

Upvotes: 3

Views: 846

Answers (1)

lissettdm
lissettdm

Reputation: 13078

I recommend you to keep the socket client reference in one place. This way you have the same socket reference in your components and the components state updates won't affect it:

socket-client.js

import io from "socket.io-client";
const ENDPOINT = "localhost:5000";

export const socket = io(ENDPOINT);

Admin.js

import { socket } from "./socket-client";

const Admin = () => {
    const [currentQuestion, setCurrentQuestion] = useState('');

    const publishQuestion = () => {
        socket.emit('question', currentQuestion);
    }
    
    useEffect(() => {
        socket.on('connect', function (data) {
            console.log('socket: ', socket.id);
            socket.on('answer', (answer) => {
                console.log('do i get here');
            })
            socket.on('setQuestion', (newQuestion) => {
                setCurrentQuestion(newQuestion);
                console.log(newQuestion);

            })

        });
    }, []); //--> empty dependency
}

Player.js

import { socket } from "./socket-client";

const Player = () => {
    const [currentQuestion, setCurrentQuestion] = useState('');

    useEffect(()=> {
     socket.on('connect', function (data) {
        console.log('socket: ', socket.id);
        socket.on('answer', (answer) => {
            console.log('do i get here');
        })
        socket.on('setQuestion', (newQuestion) => {
            setCurrentQuestion(newQuestion);
            console.log(newQuestion);

        })

    });
    }, [])

}

EDIT /

Use io.sockets.in if you want to emit to all socket in that room.

Use socket.broadcast.to to emit to all socket in that room except it.

server.js

io.on("connection", (socket) => {
  socket.join('rtd'); //--> join to rtd room;
  socket.on("question", (question) => {
    // socket.broadcast.to("rtd").emit("setQuestion", question);
    io.sockets.in("rtd").emit("setQuestion", question);
  });

  socket.on("disconnect", () => {
    console.log("User had left");
  });
});

Upvotes: 5

Related Questions