React ChartJS предотвращает добавление новых данных в состояние после его перерисовки?

Я пытаюсь обновить свою диаграмму с помощью response-chartjs-2. Я использую средство выбора даты, чтобы фильтровать различные данные и соответственно повторно отображать диаграмму, например отображать данные сегодня, вчера, за последние 7 дней и т. Д. Данные извлекаются из моей базы данных

Однако, когда диаграмма перерисовывается и перерисовывается, она добавляется в состояние, которое мне не нужно. Я просто хочу повторно отобразить новые данные, которые были запрошены, не повторно отображать и добавить к старым данным, которые были на диаграмме.

Я фактически исправлял эту проблему раньше с помощью ванильного JavaScript, потому что я не использовал реакцию. Я использовал метод destroy(), который рекомендуется использовать в документации диаграммы, но я не уверен, как использовать его с реакцией?

Итак, при дальнейшем осмотре кажется, что моя диаграмма перерисовывается нормально. Однако, когда он перерисовывается, в мое состояние chartData добавляются дополнительные данные, которые мне не нужны, я просто хочу, чтобы новые данные, которые были запрошены, отображались на диаграмме. Я все еще пытаюсь понять эту часть.

Вот мой код, у меня его много, поэтому я покажу только соответствующие части:

import React from "react";

import reportsService from "../../services/reportsService";
import update from "react-addons-update";
import moment from "moment";

import { Bar } from "react-chartjs-2";
import "chartjs-plugin-labels";
import "chartjs-plugin-datalabels";

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

    this.state = {
      chartData: {
        labels: [],
        datasets: [
          {
            //label: "Quotes",
            data: [],
            backgroundColor: []
          }
        ]
      }
    };
  }

  chartColors() {
    let colors = [];
    for (let i = 0; i < 100; i++) {
      let r = Math.floor(Math.random() * 200);
      let g = Math.floor(Math.random() * 200);
      let b = Math.floor(Math.random() * 200);
      let c = "rgb(" + r + ", " + g + ", " + b + ")";
      colors.push(c);
    }

    // Update deep nested array of objects in state
    this.setState({
      chartData: update(this.state.chartData, {
        datasets: { 0: { backgroundColor: { $set: colors } } }
      })
    });
  }

  datePicker() {
    let _this = this;
    let start = moment().subtract(29, "days");
    let end = moment();
    let showReports;
    let data;
    let reloNames = [];
    let reloCount = [];

    function focusDate(start, end) {
      $("#daterangePicker span").html(
        start.format("MMMM D, YYYY") + " - " + end.format("MMMM D, YYYY")
      );
    }

    $("#daterangePicker").daterangepicker(
      {
        startDate: start,
        endDate: end,
        ranges: {
          Today: [moment(), moment()],
          Yesterday: [
            moment().subtract(1, "days"),
            moment().subtract(1, "days")
          ],
          "Last 7 Days": [moment().subtract(6, "days"), moment()],
          "Last 30 Days": [moment().subtract(29, "days"), moment()],
          "This Month": [moment().startOf("month"), moment().endOf("month")],
          "Last Month": [
            moment()
              .subtract(1, "month")
              .startOf("month"),
            moment()
              .subtract(1, "month")
              .endOf("month")
          ]
        }
      },
      focusDate
    );

    focusDate(start, end);

    $("#daterangePicker").on("apply.daterangepicker", async function(
      event,
      picker
    ) {
      switch (picker.chosenLabel) {
        case "Today":
          showReports = await reportsService.reloQuotes({
            reportStatus: "Today"
          });

          data = showReports.recordsets[0];

          data.forEach((element, index, array) => {
            reloNames.push(element.reloNames);
            reloCount.push(element.NoofOrders);
          });

          _this.setState({
            chartData: update(_this.state.chartData, {
              labels: { $set: reloNames },
              datasets: { 0: { data: { $set: reloCount } } }
            })
          });

          console.log(_this.state);

          break;
        case "Yesterday":
          showReports = await reportsService.reloQuotes({
            reportStatus: "Yesterday"
          });

          data = showReports.recordsets[0];

          data.forEach((element, index, array) => {
            reloNames.push(element.reloNames);
            reloCount.push(element.NoofOrders);
          });

          _this.setState({
            chartData: update(_this.state.chartData, {
              labels: { $set: reloNames },
              datasets: { 0: { data: { $set: reloCount } } }
            })
          });

          console.log(_this.state);

          break;
        case "Last 7 Days":
          showReports = await reportsService.reloQuotes({
            reportStatus: "Last 7 Days"
          });

          data = showReports.recordsets[0];

          data.forEach((element, index, array) => {
            reloNames.push(element.reloNames);
            reloCount.push(element.NoofOrders);
          });

          _this.setState({
            chartData: update(_this.state.chartData, {
              labels: { $set: reloNames },
              datasets: { 0: { data: { $set: reloCount } } }
            })
          });

          console.log(_this.state);

          break;
      }
    });

    //console.log(this.state);
  }

  async reloQuotes() {
    const showreloQuotes = await reportsService.reloQuotes();
    let data = showreloQuotes.recordsets[0];
    let reloNames = [];
    let reloCount = [];

    data.forEach((element, index, array) => {
      reloNames.push(element.reloNames);
      reloCount.push(element.NoofOrders);
    });

    this.setState({
      chartData: update(this.state.chartData, {
        labels: { $set: reloNames },
        datasets: { 0: { data: { $set: reloCount } } }
      })
    });
  }

  async componentDidMount() {
    await this.chartColors();
    await this.datePicker();

    // Execute models real time thus re-rendering live data on the chart real time
    await this.reloQuotes();
  }

  render() {
    return (
      <div className="fluid-container">
        <div className="container">
          <h1>Reports</h1>
          <div className="row">
            <div className="daterangeContainer">
              <div
                id="daterangePicker"
                style={{
                  background: "#fff",
                  cursor: "pointer",
                  padding: "5px 10px",
                  border: "1px solid #ccc",
                  width: "100%"
                }}
              >
                <i className="fa fa-calendar" />
                &nbsp;
                <span /> <i className="fa fa-caret-down" />
              </div>
            </div>
          </div>
          <div className="row">
            <div className="col-md-12">
              <Bar
                data={this.state.chartData}
                height={800}
                options={{
                  maintainAspectRatio: false,
                  legend: {
                    display: false
                  },
                  scales: {
                    xAxes: [
                      {
                        ticks: {
                          beginAtZero: true,
                          autoSkip: false
                        },
                        scaleLabel: {
                          display: true
                        }
                      }
                    ]
                  },
                  title: {
                    display: true,
                    text: "Quotes",
                    fontSize: 16
                  },
                  plugins: {
                    datalabels: {
                      display: true,
                      color: "white"
                    }
                  }
                }}
                redraw
              />
            </div>
          </div>
        </div>
      </div>
    );
  }
}

export default Reportspage;


person Curious13    schedule 18.09.2018    source источник


Ответы (1)


Итак, проблема, которую вы описываете, заключается в том, что данные добавляются в состояние вашего компонента при повторной визуализации компонента. В предоставленном вами фрагменте кода вы не используете какие-либо методы жизненного цикла в React, которые могут запускаться при повторном рендеринге. И я не вижу других хуков, которые должны сработать при повторном рендеринге. Поэтому я не могу найти источник вашей проблемы.

Однако я вижу и другие проблемы, которые могут затруднить отладку для вас. Их решение может помочь вам решить настоящую проблему. В методе componentDidMount вы вызываете функции, единственной целью которых является обновление состояния. Это плохой дизайн, так как он заставит компонент немедленно повторно визуализироваться несколько раз, когда он будет монтироваться.

Лучше всего полностью подготовить объект chartData в конструкторе. Например, вы можете изменить свою функцию chartColors, чтобы она принимала объект chartData в качестве параметра и возвращала новый объект с добавленными цветами. Затем сделайте так, чтобы ваш конструктор выглядел примерно так:

constructor(props) {

   super(props);
   const chartDataWithoutColors = {
       labels: [],
       datasets: [
         {
           //label: "Quotes",
           data: [],
           backgroundColor: []
         }
       ]
     }

   const chartDataWithColor = this.chartColors(chartDataWithoutColors);

   this.state = {
     chartData: chartDataWithColor
   };
}

Удалив ненужные вызовы setState, вы упростите жизнь компонентов и повысите их производительность. Когда вы упростили свой компонент, начните отладку, удаляя по одной некритичные части, и попытайтесь решить проблему, когда проблема исчезнет. Этого должно быть достаточно, чтобы найти ошибку.

Удачи!

person pgsandstrom    schedule 21.09.2018
comment
Хорошо, я попробую использовать разные жизненные циклы вместо того, чтобы сразу устанавливать состояние при монтировании компонента. спасибо, я попробую другой подход и вернусь к вам по этому поводу. - person Curious13; 21.09.2018
comment
Поэтому я думаю, что мне нужно провести больше исследований по моей проблеме, чтобы решить возникшую у меня проблему. Что я собираюсь попробовать, так это полностью удалить весь имеющийся у меня код и попробовать другой подход к этому. Я не знаю, как закончить эту награду, но я просто посмотрю, смогу ли я попробовать другой подход. Спасибо за предложение, буду использовать его в будущем. - person Curious13; 28.09.2018