单击按钮时,React setState()不更新状态

时间:2017-10-05 04:13:59

标签: reactjs chart.js

我是React的新手并尝试使用react-chartjs-2测试一些图表组件。我有两个测试数据对象,我希望在按下更新按钮时切换它们。

已设置主App组件来处理Bar(来自react-chartjs-2)和Button组件。 state引用要用于Bar的数据对象,变量updated用于确定要在handleUpdate()方法中显示的数据。

点击Button后,应调用handleUpdate()中的App方法,该方法作为道具中onClick的参考传递。该方法评估updated并使用setState()更改正在使用的数据。我使用setState()的回调来记录状态并更改updated的值。

    import React from 'react';
    import ReactDOM from 'react-dom';
    import { Bar } from 'react-chartjs-2';

    const chart1 = {
      labels: ['Team1', 'Team2', 'Team3', 'Team4', 'Team5'],
      datasets: [{
        label: 'Team points',
        data: [503, 385, 270, 133, 65],
        backgroundColor: [
          '#4DB6AC',
          '#E57373',
          '#7986CB',
          '#F06292',
          '#E0E0E0'
        ]
      }]
    };

    const chart2 = {
      labels: ['Team1', 'Team2', 'Team3', 'Team4', 'Team5'],
      datasets: [{
        label: 'Team points 2',
        data: [303, 185, 470, 313, 65],
        backgroundColor: [
          '#4DB6AC',
          '#E57373',
          '#7986CB',
          '#F06292',
          '#E0E0E0'
        ]
      }]
    };

    class App extends React.Component {
      constructor(props) {
        super(props);

        this.handleUpdate = this.handleUpdate.bind(this);

        this.updated = false;

        this.state = {
          chartData: chart1
        }

        console.log(this.state.chartData);
        console.log(this.updated);
      }

      // Toggle between chart1 and chart2 based on value of updated
      handleUpdate() {

        if (!this.updated) {
          this.setState({
            chartData: chart2
          }, () => {
            console.log(this.state.chartData);
            this.updated = true;
          });
        }
        else {
          this.setState({
            chartData: chart1
          }, () => {
            console.log(this.state.chartData);
            this.updated = false;
          });
        }
      }

      render() {
        return(
          <div>
            <Bar data={this.state.chartData} width={650} height={400} />
            <Button handleOnClick={this.handleUpdate} />
          </div>
        );
      }
    }

    const Button = (props) => (
        <button id="update-chart" onClick={props.handleOnClick}>Update</button>
    );

    ReactDOM.render(
      <App />,
      document.getElementById('chart-container')
    );

第一次单击按钮时,一切都按预期工作,状态更新,组件重新呈现以显示新数据。但是,在后续点击中,状态保持不变,图表继续引用相同的数据。

console output - 第一个对象是初始渲染,单击按钮后会记录后续两个对象。如您所见,数据在第一次单击按钮时会发生变化,但不会在第二次或任何后续单击时发生变化。

我知道setState()是异步的并且可以批量更新,但我不明白为什么它在第一次点击时成功运行但不是每次其他点击,以及为什么回调是被召唤但国家没有改变。

修改:我认为问题与react-chartjs-2有关。如果我删除import语句以导入Bar组件,而将Bar定义为与Chartjs无关的常规函数​​组件,则App的状态成功更改每次点击两个数据对象。

所以它似乎与将数据prop从react-chartjs-2传递到Bar组件有关。虽然我不确定为什么会阻止App的状态发生变化,因为它是顶级组件。

Here is a JSFiddle显示未使用Bar作为react-chartjs-2组件时的工作原理。

1 个答案:

答案 0 :(得分:0)

我希望我可以将其用作评论,但我正在重新创建您拥有的内容并且无法复制您的错误。你的代码很难解释,这可能会让我/我们失望。这是我对handleUpdate

的实施
const chartData = this.updated ? chart2 : chart1
this.setState({chartData}, () => {
  this.updated = this.updated ? false : true
})