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