0

我正在使用 react-vis 制作折线图。我有一个名为 RoomUtilisation 的父组件和一个名为 ChartGridLine 的子组件。父级获取数据(当前使用模拟数据),然后通过道具将其传递给子级。但是,不知何故,图表仅在我多次更改下拉列表时才会呈现。子组件有时也会使用一组错误的数据,例如选择的 A 类,但使用 B 类的数据。

我尝试调试,似乎 nextProps 和 prevState 在某些情况下是相同的。请帮忙!

var dataArrayA = [];
var dataArrayB = [];

for (var item in sampleDataWeek) {
  dataArrayA.push([
    sampleDataWeek[item].week,
    sampleDataWeek[item].occupancy,
    sampleDataWeek[item].capacity
  ]);
}

for (var item in sampleDataWeekB) {
  dataArrayB.push([
    sampleDataWeekB[item].week,
    sampleDataWeekB[item].occupancy,
    sampleDataWeekB[item].capacity
  ]);
}

class RoomUltilisation extends Component {
  constructor(props) {
    super(props);
    this.state = {
      data: null,
      loading: true,
      selectedClass: "LectureA",
      selectedCourse: "COMP9517",
      counter: 0 //dummy prop
    };

    this.classOptions = [
      { value: 0, label: "LectureA" },
      { value: 1, label: "LectureB" }
    ];

    this.courseOptions = [
      { value: 0, label: "COMP9517" },
      { value: 1, label: "ARTS2663" }
    ];

    this.handleChange = this.handleChange.bind(this);
    this.addData = this.addData.bind(this);
  }

  componentDidMount() {
    if (this.state.selectedClass === "LectureA") {
      this.setState({
        data: dataArrayA
      });
    }
    this.setState({
      loading: false
    });
  }

  handleChange = event => {
    this.setState({
      [event.target.id]: event.target.value
    });

    if (this.state.selectedClass === "LectureA") {
      this.setState({
        data: dataArrayA
      });
    } else if (this.state.selectedClass === "LectureB") {
      this.setState({
        data: dataArrayB
      });
    }
  };

  render() {
    const { loading } = this.state;

    if (loading) {
      return (
        <React.Fragment>
          <NavBar />
          <SideBar />
          <div id="page-wrap">
            <h1 style={{ padding: 20 }}>Class Attendance</h1>
            <div>Loading Chart ....</div>
          </div>
        </React.Fragment>
      );
    }

    return (
      <React.Fragment>
        <NavBar />
        <SideBar />
        <div id="page-wrap">
          <h1 style={{ padding: 20 }}>Class Attendance</h1>

          <label htmlFor="course" style={this.textAreaStyle}>
            Select course
          </label>
          <select
            id="selectedCourse"
            value={this.state.selectedCourse ? this.state.selectedCourse : ""}
            onChange={this.handleChange}
          >
            {this.courseOptions.map((e, key) => {
              return (
                <option key={key} value={e.label}>
                  {e.label}
                </option>
              );
            })}
          </select>

          <label htmlFor="class" style={this.textAreaStyle}>
            Select class
          </label>

          <select
            id="selectedClass"
            value={this.state.selectedClass ? this.state.selectedClass : ""}
            onChange={this.handleChange}
          >
            {this.classOptions.map((e, key) => {
              return (
                <option key={key} value={e.label}>
                  {e.label}
                </option>
              );
            })}
          </select>

          <div id="chart-wrap">
            <ChartGridline
              data={this.state.data}
              //  key={++this.state.counter}
            />
          </div>
        </div>
      </React.Fragment>
    );
  }
}

export default RoomUltilisation;

 

class ChartGridline extends Component {
  constructor(props) {
    super(props);
    this.state = {
      highlightSeries: null,
      highlightTip: null,
      receivedData: null,
      loading: true,
      data: null,
      value: null //value of mark?
    };
    this.translatedArray = [];
    this.debouncedSetState = debounce(newState => this.setState(newState), 40);
    this._rememberValue = this._rememberValue.bind(this);
    this._forgetValue = this._forgetValue.bind(this);
  }

  async componentDidMount() {
    await this.translateSeries(this.props.data);
    this.setState({ loading: false });
  }

  static getDerivedStateFromProps(nextProps, prevState) {
    if (nextProps.data !== prevState.data) {
      return {
        data: nextProps.data
      };
    }
    // Return null if the state hasn't changed
    return null;
  }



  async componentDidUpdate(prevProps, prevState, snapshot) {
    if (JSON.stringify(this.props) !== JSON.stringify(prevProps.data)) {
      console.log("state has changed!");
      await this.translateSeries(this.props.data);
    }
    // if (snapshot.loading) {
    //   console.log("computing....!");
    // }
  }




  async translateSeries(data) {
    this.translatedArray = [1].map(i =>
      data.map(input => ({
        x: new Date(input[0]),
        y: input[1],
        capacity: input[2]
      }))
    );

    console.log("translated function: " + JSON.stringify(this.translatedArray));
  }

  _rememberValue(value) {
    this.setState({ value });
  }

  _forgetValue() {
    this.setState({ value: null });
  }

  axisProps = {
    tickSizeInner: 0,
    style: { line: { stroke: "#939393", strokeWidth: "1px" } }
  };

  hintStyle = {
    fontSize: 14,
    color: "black",
    background: "#faffe6",
    borderRadius: "5px",
    border: "3px solid #fff"
  };

  render() {
    const { highlightSeries, loading, value } = this.state;
    console.log("render method is called");

    if (loading) {
      return (
        <React.Fragment>
          <div>loading...</div>
        </React.Fragment>
      );
    }

    return (
      <div>
        <DiscreteColorLegend
          // items={["Attendance", "Enrolment"]}
          items={["Attendance"]}
          orientation="horizontal"
          // style={{ position: "absolute", textAlign: "left", right: "25%" }}

          strokeWidth="3px"
        />
        <XYPlot
          xDomain={[0, 20]}
          key="1"
          width={600}
          height={600}
          onMouseLeave={() => this.setState({ highlightTip: null })}
        >
          <XAxis
            title="semester week"
            {...this.axisProps}
            tickFormat={String}
          />
          <YAxis
            title="occupancy"
            {...this.axisProps}
            // tickFormat={d => d + "%"}
            tickFormat={d => d}
          />

          {this.translatedArray.map((d, i) => (
            <LineMarkSeries
              key={i}
              size={3}
              data={d}
              onValueMouseOver={this._rememberValue}
              onValueMouseOut={this._forgetValue}
              onSeriesMouseOver={() =>
                this.debouncedSetState({ highlightSeries: d })
              }
              onSeriesMouseOut={() =>
                this.debouncedSetState({
                  highlightSeries: null
                })
              }
              stroke={d === highlightSeries ? "black" : bgColors.Blue}
            />
          ))}
          {console.log("this.translatedArray: " + this.translatedArray)}

          {value ? (
            <Hint value={value} style={this.hintStyle}>
              <HintContent value={value} />
            </Hint>
          ) : null}
        </XYPlot>
      </div>
    );
  }
}
export default ChartGridline;

4

1 回答 1

0

嗨,根据给定的代码,我可以理解您的状态值没有正确更改,请handleChange按如下方式更改您的方法:

handleChange = event => {
    this.setState({
      [event.target.id]: event.target.value
    },() => {});

    if (this.state.selectedClass === "LectureA") {
      this.setState({
        data: dataArrayA
      },() => {});
    } else if (this.state.selectedClass === "LectureB") {
      this.setState({
        data: dataArrayB
      },() => {});
    }
  };
于 2019-07-22T10:01:57.983 回答