我正在尝试使用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
答案 0 :(得分: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
答案 1 :(得分:0)
好的,所以我尝试在服务器端的第一个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')
})
})
}
&#13;