我有一个包含子组件数组的React组件。父级从服务检索数据并将其存储在状态中。它通过props将数据从数据数组传递给每个子组件。
子组件包含更新其数据项中的值的功能。当它执行此操作时,它会触发一个事件,将更新的项目传递回父项。父级创建一个新的状态数组,包括更新的项目。
以下简化代码。
一切正常,更新数组在父的render方法中处理。但是,子组件永远不会重新呈现,因此更新的属性保持其先前的值。
如何让相关的子组件显示更新后的状态?
class SearchView extends Component {
pageSize = 20;
constructor(props) {
super(props);
this.state = {
searchTerm: this.props.searchTerm,
results: []
};
}
getResults = (page) => {
const from = (page - 1) * this.pageSize;
searchActions.termSearch(this.state.searchTerm, from, this.pageSize).then(response => {
const results = response.SearchResultViews;
this.setState({
results: results
});
});
}
componentDidMount() {
this.getResults(1);
}
refresh(result){
const results = this.state.results.map(r => {
return (r.Id === result.Id) ? result : r;
});
this.setState({
results: results
});
}
render() {
let items = [];
if (this.state.results.length > 0) {
items = this.state.results.map((result, i) => {
return <SearchItem key={i} result={result} onStatusUpdate={(r) => this.refresh(r)}></SearchItem>;
});
}
return (
<div className="r-search-result">
<Row className='clearfix scroller'>
<div className='r-container-row results'>
{ items }
</div>
</Row>
</div>
);
}
}
class SearchItem extends Component {
constructor(props) {
super(props);
}
updateStatus(newValue) {
resourceActions.updateStatus(newValue);
//Bubble an event to the Parent to refresh the result and view
if (props.onStatusUpdate) {
searchActions.get(props.result.Id).then((result) => {
props.onStatusUpdate(result);
});
}
}
render() {
return (
<a href={this.props.result.link}>
<span className="column icon-column">{this.props.result.imageUrl}</span>
<span className="column title-column">{this.props.result.titleLink}</span>
<span className="column status-column">{this.props.result.status}</span>
<span className="column button-column"><button onClick={() => this.UpdateStatus(5)}></button></span>
</a>
);
}
}
修改
在我的实际(非简化)应用程序中,子组件转换它在ComponentDidMount()
方法中传递的道具,并在状态中设置值; render方法将标记绑定到state,而不是props。在@Vishal在评论中建议的孩子的Render()
方法中设置断点后,我可以看到孩子收到更新的数据,但由于状态尚未更新,该组件不显示更新的数据。
那么问题是,如何更好地更新组件状态而不会导致无限渲染循环?
答案 0 :(得分:1)
最后,我通过将属性转换为componentWillUpdate()
中子组件的状态以及componentDidMount()
方法来解决问题。如下面的代码所示:
componentDidMount() {
if (this.props.result) {
this.prepareRender();
}
}
componentWillUpdate(nextProps, nextState) {
if (nextProps.result.status!== this.props.result.status) {
this.prepareRender();
}
}
prepareRender() {
//simplified
this.setState({
imageUrl: this.props.result.imageUrl,
titleLink: this.props.result.titleLink,
status: this.props.result.status
});
}
render() {
return (
<a href={this.props.result.link}>
<span className="column icon-column">{this.state.imageUrl}</span>
<span className="column title-column">{this.state.titleLink}</span>
<span className="column status-column">{this.state.status}</span>
<span className="column button-column"><button onClick={() => this.UpdateStatus(5)}></button></span>
</a>
);
}
<强>更新强>
在React 16.3中,不推荐使用componentWillUpdate()
方法。此解决方案应使用新的getDerivedStateFromProps()
生命周期方法,如下所述:https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html。