【问题标题】:React is sending old state to its parentReact 正在向其父级发送旧状态
【发布时间】:2016-09-14 18:10:19
【问题描述】:

当我将子组件的状态发送到其父组件时,React 将旧状态发送到父组件。

我想在每次单击 ListItem 时发送更新的状态,它工作正常并调用函数 handleItemClick。

但是当我打电话给sendStateToParent。它正在传递它的旧状态。假设我点击了ITEM1,它正在发送空数组[]。接下来我点击了ITEM2,它正在发送数组[ITEM1]

这里我实际上是在创建一个多选下拉菜单。它也可以根据获得的道具充当单选。

import React from 'react';
import ListItemComponent from './ListItem.jsx';
import DropDownButtonComponent from './DropDownButton.jsx';
import DropDownStyle from '../../../../css/sass/drop-down.scss';

module.exports = React.createClass({
  handleClick: function () {
    this.setState({open: !this.state.open});
  },
  getInitialState: function () {
    return {
      open: false,
      //listItems: this.props.listItems,
      selectedItems:[],
      title: this.props.dropdownTitle
    }
  },
  handleItemClick: function (item) {
    var selectedItems = [];
    if(this.props.multiple == true){
      selectedItems = this.state.selectedItems;
      if(selectedItems.indexOf(item)==-1){
        selectedItems.push(item);
      }else{
        selectedItems.splice(selectedItems.indexOf(item),1)
      }
      this.setState({
        title: this.state.selectedItems.length+" selected",
        selectedItems: selectedItems
      });
    } else{
      selectedItems = [];
      selectedItems.push(item);
      this.setState({
        title: item,
        selectedItems: selectedItems,
        open: false
      });
    }
    this.sendStateToParent();
  },
  sendStateToParent: function(){
    this.props.ifListChanged(this);
  },
  handleTextChange: function (event) {
    var filteredItems = [];
    this.props.listItems.map(function(item){
      if(item.toLowerCase().search(event.target.value.toLowerCase()) != -1){
        filteredItems.push(item);
      }
    },this);
    this.setState({
      listItems: filteredItems
    });
  },
  clearSelected: function(){
    this.setState({
      title: this.props.dropdownTitle,
      selectedItems: [],
    });
  },
  render: function () {
    var index = 0;
    var list=[];
    if (this.state.listItems != undefined) {
      list = this.state.listItems.map(function (item) {
        return (
          <ListItemComponent
            key={index++}
            item={item}
            whenItemClicked={this.handleItemClick}
            className={this.state.selectedItems.indexOf(item) != -1 ? "active" : ""}
          />);
      }.bind(this));
    } else {
      list = this.props.listItems.map(function (item) {
        return (
          <ListItemComponent
            key={index++}
            item={item}
            whenItemClicked={this.handleItemClick}
            className={this.state.selectedItems.indexOf(item) != -1 ? "active" : ""}
          />);
      }.bind(this));
    }

    return <div className="btn-group bootstrap-select form-control">
      <DropDownButtonComponent
        whenClicked={this.handleClick}
        title={this.state.title}
      />
      <ul className={"dropdown-menu inner dropdown-menu " + (this.state.open ? "show" : "") }>
        {this.props.search? <li><input type="text" style={{margin:"auto", maxWidth:"96%"}} onChange={this.handleTextChange} placeholder="Search"/></li> :""}
        <li className="disabled"><a>Select from below list {this.props.multiple ? <i title="clear all" style={{fontSize:"15px"}} onClick={this.clearSelected} className="text-danger fa fa-ban pull-right"></i>: ""}</a></li>
        {list}
      </ul>
    </div>
  }
});

提前致谢

【问题讨论】:

    标签: javascript reactjs state


    【解决方案1】:

    之所以 parent 获取 selecteditems 的旧值,是因为 setState() 是一个异步操作。见explanation here

    setState() 不会立即改变 this.state 而是创建一个 等待状态转换。调用后访问this.state 方法可能会返回现有值。

    所以在你的代码中,你发送一个更新状态的请求,在处理新状态之前,你调用父级中的方法,通知父级状态,它仍然有旧的状态项目。

    修复 1: 将当前状态发送给父级。
    要让项目发送当前状态,您可以使用setState() 提供的回调。在反应页面中也有解释:

    第二个(可选)参数是一个回调函数,它将被 在setState 完成并重新渲染组件后执行。

    这确保只有在setState() 完成后才调用父级。像这样的:

    this.setState(
      {
        title: item,
        selectedItems: selectedItems,
        open: false
      },
      this.sendStateToParent
    );
    

    修复 2(可选但推荐):将 selecteditems 状态移动到父项。
    如果您的父母需要了解选定项目,我建议不要将这些放在列表中。您的组件对选定项所做的唯一一件事就是在每次单击项目时将它们发送给父项。
    相反,最好:

    • 将 selectedItems 置于父项的状态
    • 从父级,将 selectedItems 作为 props 传递给组件
    • handleItemClick 逻辑移至父级
    • 在父项内部,您更新 selectedItems 列表,并设置(父项的)状态
    • 触发列表的重新渲染,以新的 selectedItems 作为道具

    【讨论】:

      猜你喜欢
      • 2019-03-16
      • 2017-06-09
      • 2016-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-06
      相关资源
      最近更新 更多