簡體   English   中英

如何根據道具的更新獲取狀態更新?

[英]How to get state to update based on an update to props?

我有一個看起來像的組件:


class Table extends Component {
  constructor(props) {
    super(props);

    this.columnDefs = columnDefs;
    this.state = {
      isLoading: true,
      showTimeoutModal: false,
      tableData: [],
      currentDate: null
    };
  }

  componentDidMount() {
    this.fetchData();
  }

  fetchData() {
    this.setState({
      isLoading: true,
      currentDate: this.props.currentDate
    });

    someApi.getData(this.props.currentDate).then(tableData => this.setState({
      tableData: tableData,
      isLoading: false
    }))
      .catch(error => {
        if (error.message === 'timeout') {
          this.setState({
            showTimeoutModal: true
          });
        } else {
          throw new Error(error.message);
        }
      });
  }

  onGridReady(params) {
    this.gridApi = params.api;
    this.gridApi.sizeColumnsToFit();
  }

  renderGrid() {
    const { tableData, isLoading, showTimeoutModal } = this.state;
    let currentView = null;
    console.log(this.props.currentDate);
    console.log(this.state.currentDate);
    if (!isLoading) {
      if (tableData) {
        currentView =
          <div>
            <AgGridReact
              columnDefs={this.columnDefs}
              rowData={tableData}
              pagination
              paginationPageSize={25}
              headerHeight="43"
              onGridReady={params => this.onGridReady(params)}
              rowSelection="single"
              animateRows="true" />
          </div>;
      } else {
        currentView = <h6>There is no job data to display!</h6>;
      }
    } else if (showTimeoutModal) {
      currentView = <div>
        <TimeoutModalComponent />
        <h6>Timed out</h6>
      </div>;

    } else {
      currentView = <LoadingComponent />;
    }

    return (
      <div>

        {currentView}
      </div>
    );
  }

  render() {
    return (
      <div>
        {this.renderGrid()}
      </div>
    );
  }

}

export default Table;

它從如下所示的 datepicker 組件中獲取 currentDate 屬性:


class DatePicker extends Component {
  constructor(props) {
    super(props);
    this.onDateChange = this.onDateChange.bind(this);
    this.state = {
      currentDate: moment(),
      focused: false
    };
  }

onDateChange() {
    this.setState({
      currentDate: this.props.currentDate
    });
  }

  render() {
    return (
      <div className="form-group">


        <SingleDatePicker
          date={this.state.currentDate}
          onDateChange={this.onDateChange}
          focused={this.state.focused}
          onFocusChange={({ focused }) => this.setState({ focused: focused })}
        />
        <TableComponent currentDate={`${this.state.currentDate}`} onDateChange={this.onDateChange} />
      </div>

    );
  }
}

export default DatePicker;

當我從日期選擇器中選擇一個新日期時,子組件上的 this.props.currentDate 會更新。 這是我想要的日期。 但是,當該道具更新時,它不會使用新的預期數據重新呈現表格。 我意識到我必須更新孩子的狀態才能重新渲染表格。 我試圖通過設置 currentDate: this.props.currentDate 在 fetchData() 方法中設置狀態來做到這一點。 但這不起作用,它不會實時更新狀態,因此網格不會重新渲染。 我想我在概念上遺漏了一些關於反應的東西,但我不確定是什么。 我認為 datePicker 組件很好,因為它可以在選擇日期時發送正確的日期,並且可以將此日期傳遞給表組件。 誰能告訴我為什么這個狀態不會更新? 或者更好的是,當 this.props.currentDate 更新時,處理狀態變化的最佳方法是什么?

編輯:我現在能夠改變狀態

componentWillReceiveProps(nextProps, nextContext) {
if (nextProps.currentDate !== this.state.currentDate) {
  this.setState({currentDate: nextProps.currentDate});
}

}

但它仍然不會在更新時重新渲染表。

好的,所以我可以看到您有多個問題:

  • 您正在DatePickerTable組件中管理 currentDate 的狀態,這是一個很大的危險信號,一個很大的 NO,您需要更好地理解“提升狀態
  • 另一個問題是<TableComponent currentDate={ ${this.state.currentDate} } 現在,在我的頭頂上,我不知道這是否真的導致您的Table不重新渲染,但從一般軟件工程的角度來看,它仍然不是一個好的綁定。 您不應該將currentDate轉換為字符串,您會丟失 React 狀態為您管理的currentDate的 ref,並且 ref 更改是觸發使用任何前端數據綁定庫(Angular、Knockout、 ReactJs, Vue.js) 顯示currentDate的組件內部可以負責字符串轉換為 HTML 顯示。

你希望把你的Table組件和DatePicker組件在父組件控制為表部件和兩個布局DatePicker組件同時管理這兩個組件之間共享的狀態。 這一變化將徹底改變你的方法,讓你騰出時間來更好地管理你的 ReactJs 應用程序。 這就是“提升狀態”。 您會發現在我建議的重構之后,您的重新渲染問題很可能甚至不存在。

使用 componentDidUpdate(prevProps) 捕獲 Table 和 DatePicker 組件中的道具更改事件。

避免使用 componentWillReceiveProps。

根據react.org,使用這種生命周期方法通常會導致錯誤和不一致

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM