[英]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});
}
}
但它仍然不会在更新时重新渲染表。
好的,所以我可以看到您有多个问题:
DatePicker
和Table
组件中管理 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.