繁体   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