【问题标题】:How to re-render a component when receiveing data from socket.io?从 socket.io 接收数据时如何重新渲染组件?
【发布时间】:2018-04-23 20:02:32
【问题描述】:

我正在尝试使用 React 和 socket.io 构建一个实时多人游戏,所以当用户登录时,我使用 socket.io 在服务器端的数组中传递他的名字,然后游戏组件出现,我映射数组以显示所有玩家的姓名。

所以,第一个玩家登录,他的名字显示在他的窗口上,第二个玩家登录然后在他的窗口上得到他的名字+第一个玩家的名字,但是第一个玩家的窗口没有更新以显示第二个玩家在他之后登录。

知道如何在从 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

【问题讨论】:

  • 是console.log('handleData' + data);发生了吗?
  • console.log('handleData ' + data); 打印什么吗?
  • 是的,它确实打印了玩家数组

标签: javascript reactjs socket.io


【解决方案1】:

好的,现在它可以使用 io.emit 而不是 socket.emit + socket.broadcast.emit 这是工作示例

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

【讨论】:

    【解决方案2】:

    好的,所以我尝试在服务器端的第一个 socket.emit 之后添加一个 socket.broadcast.emit,它可以工作,所有新窗口都会在更新时获取新的玩家列表,但我不知道为什么! 有人对此有想法吗?

    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')
         })
      })
     }

    【讨论】:

    • 你是不是错过了playerConnected,这是从哪里调用的?请提供完整的示例和所有文件,因为您似乎没有显示所有文件
    • 是的,抱歉,我添加了文件,它在 fetch line 35 中
    • 我在前面有一个表单,当前面验证正常时,我会向服务器发送一个获取帖子,如果服务器说正常,那么我将它添加到数据库并向前面发送响应,然后从那里我在承诺中做一个 socket.emit
    • 好的,现在我用 io.emit 替换了 socket.emit 和 socket.broadcast.emit,一切正常
    猜你喜欢
    • 1970-01-01
    • 2021-10-27
    • 1970-01-01
    • 2018-08-12
    • 2019-06-01
    • 2020-02-13
    • 1970-01-01
    • 1970-01-01
    • 2016-01-18
    相关资源
    最近更新 更多