Реагируйте ChartJS, чтобы предотвратить добавление новых данных в состояние после их перерисовки? - PullRequest
0 голосов
/ 18 сентября 2018

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

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

Я фактически исправил эту проблему раньше с помощью vanilla 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;

1 Ответ

0 голосов
/ 21 сентября 2018

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

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

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

constructor(props) {

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

   const chartDataWithColor = this.chartColors(chartDataWithoutColors);

   this.state = {
     chartData: chartDataWithColor
   };
}

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

Удачи!

...