React Socket.io:只能更新已安装或安装的组件

时间:2017-05-04 15:00:23

标签: reactjs socket.io

我正在反复发出警告

警告: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);

组件卸载时关闭套接字。我还尝试在组件卸载时进行日志记录,并且在此之前它没有卸载,那么为什么我得到错误呢?

1 个答案:

答案 0 :(得分:0)

  

这可能与您的组件连接到Redux的事实有关   同样,这意味着还有另一个实例(没有安装)   听插座。 - 我的猜测是尝试断开redux和   看看是否有帮助。在任何情况下,我会移动套接字和可选   redux到一个容器组件,这个问题太多了   组件调试它很容易! - 帕特里克

谢谢Patrick!