簡體   English   中英

即使將更新的值從父級傳遞給子級,也不會呈現子級

[英]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.

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