Davey
Davey

Reputation: 53

How to re-render a component when receiveing data from socket.io?

I'm trying to build a realtime multiplayer game with React and socket.io, so when the user is logged in i pass his name in an array on server side with socket.io and then the game component shows up and i map the array to display all players name.

So, first player logs in, his name is shown on his window, second player logs in then gets his name + the first player name on his window, but the window of the first player doesnt update to show the second player that logged after him.

Any idea on how to trigger a render on the component when data is received from socket.io ?

import React, { Component } from 'react'
import { Button } from 'semantic-ui-react'
import socket from '../api'

class connectedUsers extends Component {
  constructor(props) {
    super(props)

    this.state = {players : []}
  }

  handleData = (data) => {
    this.setState({players: data})
    console.log('handleData ' + data);
  }

  componentDidMount() {
    socket.on('playerList', this.handleData)
  }

  render() {
    console.log('render ' + this.state.players);
    return(
      <div>
        {this.state.players.map(player =>
          <Button basic color='violet' key={player}>{player}</Button>
        )}
      </div>
    )
  }

}

export default connectedUsers

import openSocket from 'socket.io-client'

const socket = openSocket('http://localhost:3001')

export default socket

module.exports = function (io) {
  let players = []

  io.on('connection', socket => {


    socket.on('playerConnected', (player) => {

      players.push(player)

      socket.emit('playerList', players)
    })

    socket.on('disconnect', () => {

       console.log('user disconnected')
     })
  })
 }

import React, { Component } from 'react'
import { Form, Message } from 'semantic-ui-react'
import { Redirect } from 'react-router-dom'
import socket from '../api'

class PseudoForm extends Component {
  state = { name: '', pseudoDispo: false, pseudoValide: true, pseudoNonDispo: false}

  handleChange = (e, { name, value }) => this.setState({ [name]: value })

  handleSubmit = (e) => {
    e.preventDefault()

    const { name } = this.state


    this.setState({pseudoDispo: false})
    this.setState({pseudoNonDispo: false})

    if(name.length > 3) {
      this.setState({pseudoValide: true})

      fetch('/postpseudo', {
        method: "POST",
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({pseudo: name})
      })
        .then(res => res.json())
        .then(data => {
          if(data.pseudoDispo) {
            this.setState({pseudoDispo: data.pseudoDispo})
            socket.emit('playerConnected', name)
          } else {
            this.setState({pseudoNonDispo: true})
            }
          })
        .catch(error => console.error(error))


    } else {
      this.setState({pseudoValide: false})
    }
  }

  render() {
    const { name } = this.state
    const redirectToGame = this.state.pseudoDispo ? <Redirect to={{pathname: '/game'}} /> : true
    return(
      <div>
        {redirectToGame}
          <Form
            success={this.state.pseudoDispo}
            error={this.state.pseudoNonDispo}
            warning={!this.state.pseudoValide}
            onSubmit={this.handleSubmit}
          >
            <Form.Input
              placeholder="Pseudo"
              name="name"
              width={4}
              value={name}
              onChange={this.handleChange}
            />
            <Message
              success
              header='Pseudo Disponible'
            />
            <Message
              error
              header='Pseudo déja pris'
            />
            <Message
              warning
              header='Le pseudo est trop court'

            />
            <Form.Button primary >Envoyer</Form.Button>
          </Form>
      </div>
    )
  }
}

export default PseudoForm

Upvotes: 2

Views: 1922

Answers (2)

Davey
Davey

Reputation: 53

Ok so now it works with io.emit instead of socket.emit + socket.broadcast.emit Here's the working example

module.exports = function (io) {
  let players = []

  io.on('connection', socket => {


    socket.on('playerConnected', (player) => {

      players.push(player)

      io.emit('playerList', players)
    })


    socket.on('disconnect', () => {

       console.log('user disconnected')
     })
  })
 }

import React, { Component } from 'react'
import ConnectedUsers from '../components/connectedUsers'
import socket from '../api'


class Game extends Component {
  constructor() {
    super()

    this.state = { players: [] }
  }

  componentDidMount() {
    socket.on('playerList', this.handleData)
  }
  
  handleData = (playerList) => {
    this.setState({players: playerList})
  }

  render() {

    return(
      <div>
        <ConnectedUsers list={this.state.players}/>
      </div>
    )
  }
}

export default Game

import React, { Component } from 'react'
import { Button } from 'semantic-ui-react'

class connectedUsers extends Component {
  constructor(props) {
    super(props)


    this.state = {players : []}
  }



  render() {
    console.log('render ' + this.state.players);
    return(
      <div>
        {this.props.list.map(player =>
          <Button basic color='violet' key={player}>{player}</Button>
        )}
      </div>
    )
  }

}

export default connectedUsers

Upvotes: 1

Davey
Davey

Reputation: 53

Ok so i tried adding adding a socket.broadcast.emit after the first socket.emit on server side, and it works, all the new windows get the new list of players on update, but I have no idea why ! Do someone have an idea about this ?

module.exports = function (io) {
  let players = []

  io.on('connection', socket => {


    socket.on('playerConnected', (player) => {

      players.push(player)

      socket.emit('playerList', players)
      socket.broadcast.emit('playerList', players)
    })


    socket.on('disconnect', () => {

       console.log('user disconnected')
     })
  })
 }

Upvotes: 0

Related Questions