response-chartjs-2 не обновляет график при обновлении состояния

Я создаю приложение панели мониторинга, которое извлекает данные из конечной точки и использует метод setState для назначения переменных из JSON, возвращаемых конечной точкой, в переменные состояния. Когда я вношу изменения в состояние, некоторые компоненты, такие как "response-svg-gauge", будут обновляться, но "response-chartjs-2" не обновляется.

Ниже приведен пример того, как мое состояние изменяется в моем фактическом приложении. В этом примере будет отображаться правильное значение переменных состояния в консоли разработчика Chrome, но не обновляется соответственно DOM.

import React, { Component } from 'react';
import {Doughnut} from 'react-chartjs-2';

class DoughnutExample extends Component {
  state = {
    data: {
        labels: [
            'Red',
            'Green',
            'Yellow'
        ],
        datasets: [{
            data: [300, 50, 100],
            backgroundColor: [
            '#FF6384',
            '#36A2EB',
            '#FFCE56'
            ],
            hoverBackgroundColor: [
            '#FF6384',
            '#36A2EB',
            '#FFCE56'
            ]
        }]
    }
  }

  componentDidMount() {
    this.timer = setInterval(
      () => this.increment(),
      1000
    )
  }

  componentWillUnmount() {
    clearInterval(this.timer)
  }

  increment() {
    let datacopy = Object.assign({}, this.state.data)
    datacopy.datasets[0].data[0] = datacopy.datasets[0].data[0] + 10
    console.log(datacopy.datasets[0].data[0])
    this.setState({data: datacopy})
  }

  render(){
    return(
      <div>
      <Doughnut data = {this.state.data}/>
      </div>
    )
  }
}

export default DoughnutExample;

Я правильно использую методы жизненного цикла? Этот код обновит значение круговой диаграммы, переменную состояния, но не будет правильно отображать DOM.

Ответ 1

Потенциальная проблема, которую я вижу, заключается в том, что вы пытаетесь обновить вложенное свойство, пока вы его мутируете. Поэтому, если Doughnut передает части data другим компонентам, они не будут уведомлены о том, что реквизит изменился. Поэтому нужно сделать глубокий клон:

increment() {
    const datasetsCopy = this.state.data.datasets.slice(0);
    const dataCopy = datasetsCopy[0].data.slice(0);
    dataCopy[0] = dataCopy[0] + 10;
    datasetsCopy[0].data = dataCopy;

    this.setState({
        data: Object.assign({}, this.state.data, {
            datasets: datasetsCopy
        })
    });
}

Вам также может потребоваться привязать функцию, как предлагает @Janick Fisher.

Ответ 2

Проверьте эту ссылку. Вы можете видеть, что он привязывает функцию к компоненту.

https://codepen.io/gaearon/pen/xEmzGg?editors=0010

// This binding is necessary to make 'this' work in the callback
    this.handleClick = this.handleClick.bind(this);

Ответ 3

Вы также можете очистить переменную состояния и заполнить ее снова как

                this.setState({
                    mainData: {}
                });
                this.setState({
                    mainData: md
                });

в то время как md был инициализирован со значением mainData