web-dev-qa-db-fra.com

react-chartjs-2 ne met pas à jour le graphique lorsque l'état est mis à jour

Je crée une application de tableau de bord qui récupère les données d'un point de terminaison et utilise la méthode setState pour affecter des variables à partir du JSON renvoyé par le point de terminaison aux variables d'état. Lorsque je modifie un état, certains composants tels que "react-svg-gauge" seront mis à jour mais "react-chartjs-2" ne sera pas mis à jour.

Le code ci-dessous est un exemple de la façon dont mon état change dans mon application réelle. Cet exemple affiche la valeur correcte des variables d'état dans la console de développement Chrome, mais ne met pas à jour le DOM en conséquence.

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;

Est-ce que j'utilise correctement les méthodes du cycle de vie? Ce code met à jour la valeur du graphique à secteurs, la variable d'état, mais ne restitue pas correctement le DOM.

10
Bryan Licata

Le problème potentiel que je vois est que vous essayez de mettre à jour la propriété imbriquée pendant que vous la modifiez. Ainsi, si Doughnut transmet des parties de data à d'autres composants, ils ne seront pas informés que les accessoires ont changé. Il est donc nécessaire de faire un clone en profondeur:

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
        })
    });
}

Vous pouvez également avoir besoin de lier la fonction, comme le suggère @Janick Fisher.

8
Tomasz Mularczyk

Vérifiez ce lien. Vous pouvez voir qu'il lie la fonction au composant.

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);
0
Janick Fischer