ComponentDidUpdate即使在条件包裹时也会导致无限渲染

问题描述 投票:0回答:1

我正在尝试从Google Analytics报告API中提取一些数据,并在顶点图表库中显示数据。我成功地做到了这一点。但是,我现在想要过滤选项,如果用户在日期范围选择器反应包装器中选择某个日期,那么顶点图表数据将从API更新。

我正在努力弄清楚我的数据何时更新,用生命周期方法中的新状态更新状态?我想我做的很小,我只是不知道它是什么。我查阅了生命周期方法的文档,并说它确保将其包装在我所做的条件中。但是,当满足else条件时,它会导致无限渲染。

这是我的代码:(我坚持的错误是componentWillUpdate生命周期方法)其他一切正常。

import React from "react";

import Header from "../common/Header";
import Footer from "../common/Footer";

import moment from "moment";
import $ from "jquery";
import ApexCharts from "apexcharts";
import Chart from "react-apexcharts";
import DateRangePicker from "react-bootstrap-daterangepicker";

const VIEW_ID = "";

class Charts extends React.Component {
  constructor(props) {
    super(props);
    this.printResults = this.printResults.bind(this);
    this.pageViews = this.pageViews.bind(this);
    this.handleError = this.handleError.bind(this);
    this.state = {
      loading: true,
      filterstartDate: "",
      filterendDate: "",
      // Start Series Bar State

      ChartOne: {
        chart: {
          id: "ChartOne"
        },
        colors: ["#e31d1a"],
        xaxis: {
          categories: [],
          labels: {
            style: {
              colors: []
            }
          },
          title: {
            text: "Locations"
          }
        },
        yaxis: {
          labels: {
            style: {
              colors: []
            }
          },
          title: {
            text: "Count"
          }
        }
      },
      ChartOneSeries: [],
  }

  pageViews = async () => {
    window.gapi.client
      .request({
        path: "/v4/reports:batchGet",
        root: "https://analyticsreporting.googleapis.com",
        method: "POST",
        body: {
          reportRequests: [
            {
              viewId: VIEW_ID,
              dateRanges: [
                {
                  startDate: "7daysAgo",
                  endDate: "today"
                }
              ],
              metrics: [
                {
                  expression: "ga:pageviews"
                }
              ],
              dimensions: [
                {
                  name: "ga:country"
                }
              ],
              orderBys: [{ fieldName: "ga:pageviews", sortOrder: "DESCENDING" }]
            }
          ]
        }
      })
      .then(this.printResults, this.handleError);
  };

  componentDidMount() {
    $.getScript("https://apis.google.com/js/client:platform.js").done(() => {
      window.gapi.signin2.render("my-signin2", {
        scope: "profile email",
        width: 240,
        height: 50,
        longtitle: true,
        theme: "dark",
        onsuccess: this.pageViews,
        onfailure: this.handleError
      });
    });
  }

  //log the data
  printResults(response) {
    let pageviewLocation = [];
    let pageviewCount = [];
    let pageviewTotal = response.result.reports[0].data.totals[0].values[0];
    let totalComma = pageviewTotal
      .toString()
      .replace(/\B(?=(\d{3})+(?!\d))/g, ",");

    response.result.reports[0].data.rows.map(value => {
      //console.log(value.dimensions);
      pageviewLocation.push(value.dimensions[0]);
      pageviewCount.push(parseInt(value.metrics[0].values[0]));
    });

    //console.log(total);

    this.setState({
      loading: false,
      ChartOne: {
        title: {
          text: totalComma,
          align: "center",
          style: {
            fontSize: "20px"
          }
        },
        subtitle: {
          text: "Total Page Views",
          align: "center",
          style: {
            fontSize: "14px",
            cssClass: "apexcharts-yaxis-title"
          }
        },
        plotOptions: {},
        ...this.state.ChartOne,
        xaxis: {
          width: 1,
          ...this.state.ChartOne.xaxis,
          labels: {
            show: false,
            ...this.state.ChartOne.xaxis.labels,
            style: {
              ...this.state.ChartOne.xaxis.labels.style
            }
          },
          categories: pageviewLocation
        },
        yaxis: {
          min: 0,
          ...this.state.ChartOne.yaxis,
          labels: {
            //show: false,
            ...this.state.ChartOne.yaxis.labels,
            style: {
              ...this.state.ChartOne.yaxis.labels.style
            }
          }
        }
      },
      ChartOneSeries: [
        {
          name: "Total Page Views",
          data: pageviewCount
        }
      ]
    });
  }

  componentDidUpdate(prevProps, prevState) {
    if (this.state.filterstartDate === "" && this.state.filterendDate === "") {
      console.log("they are empty");
    } else {
      this.setState({
        // this fails immediately once the condition is met
        test: "success!"
      });
    }
  }

  Datepicker = async (event, picker) => {
    this.setState({
      filterstartDate: moment(picker.startDate._d).format("YYYY-MM-DD"),
      filterendDate: moment(picker.endDate._d).format("YYYY-MM-DD")
    });

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

  //or the error if there is one
  handleError(reason) {
    console.error(reason);
    console.error(reason.result.error.message);
  }

  render() {
    //console.log();

    return (
      <div className="containerfluid" id="fullWidth">
        <Header />
        <div className="container" id="chartContainer">
          <h1>Site Analytics</h1>
          <div className="row">
            <div className="col-md-12">
              <DateRangePicker
                startDate={moment().format("MM-DD-YYYY")}
                endDate={moment().format("MM-DD-YYYY")}
                onApply={this.Datepicker}
              >
                <button className="btn btn-info">
                  <i className="fas fa-filter">
                    <span
                      style={{
                        fontFamily: "Roboto, san-serif",
                        fontWeight: "normal",
                        padding: "5px"
                      }}
                    >
                      Filter Date
                    </span>
                  </i>
                </button>
              </DateRangePicker>
            </div>
          </div>
          <div className="row">
            <div className="col-md-4">
              {/* Chart One Line */}
              {this.state.loading ? (
                <React.Fragment>
                  <i className="fas fa-spinner fa-3x" id="loader" /> Please wait
                  ...!
                </React.Fragment>
              ) : (
                <div className="chartContainer">
                  <Chart
                    options={this.state.ChartOne}
                    series={this.state.ChartOneSeries}
                    type="line"
                    width={400}
                    height={300}
                  />
                </div>
              )}
            </div>
          </div>
          <div id="my-signin2" />
        </div>
        <Footer />
      </div>
    );
  }
}

export default Charts;
reactjs
1个回答
4
投票

当你使用setState时,你会再次触发生命周期。如果你没有将你的filterstartDatefilterendDate设置为"",你将继续无限地调用setState。

componentDidUpdate(prevProps, prevState) {
    if (this.state.filterstartDate === "" && this.state.filterendDate === "") {
      console.log("they are empty");
    } else {
      this.setState({
        filterstartDate: "",
        filterendDate: "",
        test: "success!"
      });
    }
  }
© www.soinside.com 2019 - 2024. All rights reserved.