【发布时间】:2017-05-05 03:23:40
【问题描述】:
我不断收到警告
警告:setState(...):只能更新已安装或已安装的组件。这通常意味着您在未安装的组件上调用了 setState()。这是一个无操作。请检查 RoundView 组件的代码。
它指向一个 socket.io 行
socket.on(
'rankings',
(payload) => this.setState({
totals: payload.totals,
scores: payload.scores
},this.updateRoundProgress)
);
但是该组件显然已安装并且一切似乎都运行良好,当捕获“排名”事件时,状态会更新得很好。完整代码如下:
https://github.com/JellyKid/ballsavr/blob/master/Frontend/app/components/user/RoundView.jsx
import React from 'react';
import handleFetch from '../../helpers/handleFetch';
import { Grid, Col, PageHeader } from 'react-bootstrap';
import { connect } from 'react-redux';
import update from 'immutability-helper';
import ConfirmScores from './view/ConfirmScores';
import Rankings from './view/Rankings';
import Scores from './view/Scores';
import Group from './view/Group';
import Manage from './view/Manage';
const socket = require('socket.io-client')('/round',{
path: '/api/socket.io',
autoConnect: false
});
class RoundView extends React.Component {
constructor(props) {
super(props);
this.state = {
round: this.props.round || {
event: {
title: 'Loading...'
},
name: "Please wait",
tables: [],
players: []
},
scores: [],
totals: []
};
this.refreshScores = this.refreshScores.bind(this);
this.updateRoundProgress = this.updateRoundProgress.bind(this);
}
componentDidMount(){
this.handleSocket();
let fetches = [
handleFetch('GET',`/api/score/totals?round=${this.props.params.roundID}`),
handleFetch('GET',`/api/score/round?id=${this.props.params.roundID}`)
];
if(!this.props.round){
fetches.push(handleFetch('GET', `/api/round/${this.props.params.roundID}`));
}
return Promise.all(fetches)
.then(
(res) => {
this.setState({
totals: res[0].payload,
scores: res[1].payload,
round: this.props.round || res[2].payload
});
}
).catch((err) => {console.log(err);});
}
handleSocket(){
socket.open();
socket.on(
'connect',
() => socket.emit('join round', this.props.params.roundID)
);
socket.on(
'rankings',
(payload) => this.setState({
totals: payload.totals,
scores: payload.scores
},this.updateRoundProgress)
);
socket.on(
'connect_error',
() => setTimeout(socket.open, 1000)
);
}
updateRoundProgress(){
if(this.props.player.admin){
let scores = this.state.scores.filter((score) => score.confirmed).length;
let progress = Math.floor((scores/(this.state.round.tables.length * this.state.round.players.length))*100);
return this.setState(update(
this.state,
{round: {progress : {$set: progress}}}
));
}
}
refreshScores(){
handleFetch('GET',`/api/score/round?id=${this.props.params.roundID}`)
.then(
(res) => this.setState({scores: res.payload})
).catch((err) => {console.log(err);});
}
componentWillUnmount(){
socket.close();
}
render(){
let player = this.state.round.players.find((p) => p.user._id === this.props.player._id);
let groupName = (player) ? player.group : "";
return (
<Grid>
<Col md={6} mdOffset={3}>
<PageHeader>
{this.state.round.event.title}<br/><small>{this.state.round.name}</small>
</PageHeader>
<Rankings
totals={this.state.totals}
players={this.state.round.players}
player={this.props.player}
/>
<hr />
<Group
group={groupName}
players={this.state.round.players}
/>
<hr />
<Scores
player={this.props.player}
scores={this.state.scores}
round={this.state.round}
group={groupName}
/>
<hr />
<ConfirmScores
scores={this.state.scores}
player={this.props.player}
/>
<hr />
<Manage
round={this.state.round}
player={this.props.player}
/>
</Col>
</Grid>
);
}
}
function mapStateToProps(state, ownProps) {
return {
round: state.rounds.find((round) => round._id === ownProps.params.roundID),
player: state.user
};
}
export default connect(mapStateToProps)(RoundView);
当组件卸载时,我关闭了套接字。我还尝试在组件卸载时进行日志记录,并且在此之前它没有卸载,那么为什么我会收到错误消息?
【问题讨论】:
-
你不断收到这个警告?
-
这可能与您的组件也连接到 Redux 的事实有关,这意味着有另一个实例(未安装)正在侦听套接字。 - 我的猜测是尝试断开 redux 并查看是否有帮助。在任何情况下,我都会将套接字和可选的 redux 移动到容器组件中,这个组件上发生的事情太多了,无法轻松调试它!
-
这就是问题所在。我将 socket.io 部分分成了它自己的组件。谢谢!