React正在将旧状态发送给其父级 [英] React is sending old state to its parent

查看:69
本文介绍了React正在将旧状态发送给其父级的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

When I'm sending state of the child component to its parent component, React is sending old state to the parent component.

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

I want to send the updated state on every click on ListItem which is properly working and calling the function handleItemClick.

但是当我打电话给sendStateToParent时.它正在通过它的旧状态.假设我单击了ITEM1,它正在发送空数组[].接下来,我单击了ITEM2,它正在发送数组[ITEM1].

But when I'm calling sendStateToParent. It is passing old state of it. Suppose I have clicked on ITEM1, it is sending empty array[]. Next I have clicked on ITEM2, it is sending array [ITEM1].

在这里,我实际上是在创建一个多选下拉列表.也可以根据所获得的道具作为单一选择.

Here I'm actually creating a multiselect dropdown. which also can act as single select based on props it is getting.

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>
  }
});

预先感谢

推荐答案

父级之所以会获得selecteditems的旧值,是因为setState()是异步操作.参见此处解释:

The reason parent gets the old value of selecteditems, is because setState() is an asynchronous operation. See explanation here:

setState()不会立即使this.state突变,但会创建一个 等待状态转换.调用此后访问this.state 方法可能会返回现有值.

setState() does not immediately mutate this.state but creates a pending state transition. Accessing this.state after calling this method can potentially return the existing value.

因此,在您的代码中,您发送了一个更新状态的请求,并在处理新状态之前,在父级中调用该方法,以告知父级状态,该状态仍然具有旧状态.项目.

So in your code, you send a request to update state, and before the new state is processed, you call the method in the parent, to inform parent about state, which still has the old items.

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

Fix 1: send current state to parent.
To get the item to send the current state, you could use the callback that setState() provides. Explained also in react pages:

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

The second (optional) parameter is a callback function that will be executed once setState is completed and the component is re-rendered.

这可确保仅在setState()完成后才能进行对父级的调用.像这样:

This ensures that the call to parent is made only after setState() is finished. Something like this:

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

修复2 (可选,但推荐):将selecteditems状态移到父级.
如果您的父母需要了解所选项目,我建议不要将其置于列表状态.您的组件对所选项目所做的唯一一件事就是每次单击某个项目时将其发送给父项.
相反,最好:

Fix 2(optional but recommended): move selecteditems state to parent.
If your parent needs to know about selecteditems, I would advise not to put these in state of the list. The only thing your component does with the selecteditems is to send them to the parent, every time an item is clicked.
Instead, it is better to:

  • 将selectedItems置于父项状态
  • 从父级,将selectedItems作为道具传递给组件
  • handleItemClick逻辑移至父级
  • 在父级内部,您更新selectedItems列表,并设置(父级)状态
  • 使用新的selectedItems作为道具触发列表的重新呈现
  • put selectedItems in state of the parent
  • from the parent, pass selectedItems as props to the component
  • move the handleItemClick logic to the parent
  • inside the parent, you update the list of selectedItems, and set state (of the parent)
  • triggering a re-render of the list, with the new selectedItems as props

这篇关于React正在将旧状态发送给其父级的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆