![](/img/trans.png)
[英]Why isn't child component re-rendered even though parent state is updated using hooks
[英]Even after passing updated value from parent to child, child is not rendered
在父組件中,我從服務器接收數據,然后將此數據映射為jsx格式。 在此映射內部,我有一個子組件,並嘗試將值從父狀態傳遞給子狀態作為屬性,但是,當我更新此值的狀態時,不會執行子項的渲染功能。
預期的行為:作為用戶,我看到一個項目列表。 如果我單擊某個項目,則它應變為選中狀態。
export class ReactSample extends React.Component {
constructor(props){
super(props);
this.state = {
items: [],
mappedItems: [],
selectedIds: [],
isSelected: false,
clickedTripId: null
};
this.toggleSelection = this.toggleSelection.bind(this);
}
componentWillMount(){
console.log("Component mounting")
}
toggleSelection (id, e) {
if(!_.includes(this.state.selectedIds, id)) {
this.setState((state) => ({selectedIds:
state.selectedIds.concat(id)}));
this.setState(() => ({clickedTripId: id}));
this.mapItems(this.state.items);
}
}
componentDidMount() {
const self = this;
MyService.getItems()
.then(res => {
self.setState(() => ({ items: res.allItems }));
self.setState(() => ({ mappedItems:
this.mapItems(res.allItems) }));
}
)
}
mapItems (items) {
return items.map(trip => {
return (
<li key={trip.id} onClick={(e) => (this.toggleSelection(trip.id,
e))}>
<span>{trip.title}</span>
<Tick ticked={this.state.clickedTripId}/>
<span className="close-item"></span>
</li>
);
});
}
getItems() {
}
render() {
return (
<div>
<a className="title">This is a react component!</a>
<Spinner showSpinner={this.state.items.length <= 0}/>
<div className="items-container">
<ul id="itemsList">
{this.state.mappedItems}
</ul>
</div>
</div>
);
}
}
export class Tick extends React.Component {
constructor(props) {
super(props);
}
render() {
console.log('RENDER');
return (<span className={this.props.ticked ? 'tick display' :
'tick hide' }></span>);
}
}
我看到幾個問題。
在toggleSelection
您不會對mapItems的結果做任何事情。 如果您mappedItems
狀態中刪除mappedItems
,而只是在render方法中調用mapItems
,則可以避免這種錯誤。
另一個問題是您正在傳遞this.state.clickedTripId
作為已ticked
屬性。 我假設您打算傳遞類似this.state.clickedTripId === trip.id
。
萊恩已經說了,問題是, mappedItems
在哪里都不更新toggleSelection
被點擊。 從代碼中可以明顯mapItems
,mapItems以jsx格式返回數據。 要對其進行更新,我必須調用this.setState({mappedItems: this.mapItems(this.state.items)})
,這意味着我調用了mapItems
,然后將結果分配給該狀態。 在這種情況下,我的列表將被更新, Tick
組件將收到this.state.clickedItemId
作為tick
屬性。 要使此代碼正常工作,還需要解決另一個問題:在this.state.clickedItemId
更新后,需要更新此映射列表。 setState
方法是異步的,這意味着僅在this.state.clickedItemId
更新之后this.state.clickedItemId
必須調用this.setState({mappedItems: this.mapItems(this.state.items)})
。 為此, setState
方法可以接收回調函數作為第二個參數。 代碼段如下:
toggleSelection (id, e) {
if(!_.includes(this.state.selectedIds, id)) {
this.setState((state) => ({
clickedItemId: id,
selectedIds: state.selectedIds.concat(id)
}), () => this.setState({mappedItems: this.mapItems(this.state.items)}));
}
}
在這種情況下,在執行mapItems
函數時,來自此處所需狀態的所有數據都將已更新:
mapItems (items) {
return items.map(item => {
return (
<li key={item.id} onClick={(e) => (this.toggleSelection(item.id, e))}>
<span>{item.title}</span>
<span>{this.state.clickedItemId}</span>
<Tick ticked={this.state.clickedItemId === item.id}/>
<span className="close-item"></span>
</li>
);
});
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.