简体   繁体   中英

SocketIO Not Emitting an Action in React

The Goal I am looking for numerous users to sign into a game room, such as game/##### . When a user hits that url, their user object is created and shared to the state for any other user in that room to view.

The Problem In componentDidMount I call my Socket api function and pass in the userObj and room value. This information makes it to the api function, and then to the server listener as well. However, when the server emits the join room event, the frontend doesn't seem to hear it and respond by updating the state.game.users object with the new user.

The Code

server.js

var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);

server.listen(8000);

io.on('connection', function (socket) {
  socket.on('join room', (userObj, room) => {
    socket.join(room).emit('join room', userObj);
  });

  socket.on('join chat', (msgObj, room) => {
    socket.in(room).emit('join chat', msgObj);
  });

  socket.on('chat message', (msgObj, room) => {
    socket.in(room).emit('chat message', msgObj);
  });
});

api.js

import io from 'socket.io-client';
const socket = io.connect('http://localhost:8000');

export const joinRoom = (userObj, room) => {
  socket.emit('join room', userObj, room);
}

export const joinChat = (msgObj, room) => {
  socket.emit('join chat', msgObj, room);
}

export const chatMessage = (msgObj, room) => {
  socket.emit('chat message', msgObj, room);
}

component

import { joinRoom, joinChat, chatMessage } from './../../api';

class GameBoard extends Component {
  constructor(props) {
    super(props);
    this.state = {
      loading: true,
      game: {
        id: props.match.params.gameid,
        users: {},
        messages: []
      }
    };

    this.socket = io('http://localhost:8000');

    this.postUsername = this.postUsername.bind(this);
    this.getBoardValues = this.getBoardValues.bind(this);
    this.buildUserData = this.buildUserData.bind(this);
  }

  componentDidMount() {
    this.socket.on('join room', (userObj) => {
      this.postUser(userObj);
    });

    this.socket.on('join chat', (msgObj) => {
      this.postMessage(msgObj);
    });

    this.socket.on('chat message', (msgObj) => {
      this.postMessage(msgObj);
    });

    this.socket.on('connect', () => {
      joinRoom(this.buildUserData(), this.state.game.id);
    });
  }

  postUser(userObj) {
    const game = this.state.game;
    game.users[userObj.id] = userObj;
    this.setState({ game });
  }
...

Repo https://github.com/yuschick/horror-bingo

I think the problem is in this.socket = io('http://localhost:8000'); . It means you create another connection to your server with a new socket. So when you emit a new event from server, your socket in the component cannot receive it because it has a different socket.

You can export const socket = io.connect('http://localhost:8000'); , import it into your component and use it socket.on ...

In case you want to emit an event to another connected socket, you can use socket.broadcast.emit or io.emit . You can check the cheat sheet here https://socket.io/docs/emit-cheatsheet/ . For example:

io.on('connection', function (socket) {
    socket.on('join room', (userObj, room) => {
        socket.join(room).emit('join room', userObj); \\<-- this will only let the socket from front end which emit 'join room' receive event

        socket.broadcast.to(room).emit(`join room', userObj); \\<-- this will let all socket from front end(in the same room) receive 'join room' event except the one which emit.
    });

    socket.on('join chat', (msgObj, room) => {
        socket.in(room).emit('join chat', msgObj);
    });

    socket.on('chat message', (msgObj, room) => {
        socket.in(room).emit('chat message', msgObj);
    });
});

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