2016-05-18 29 views
3

當我將子組件的狀態發送給其父組件時,React將舊狀態發送給父組件。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> 
    } 
}); 

在此先感謝

回答

3

父之所以得到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,通過selectedItems道具到組件
    • 動議handleItemClick邏輯到母體
    • 內部父級,您更新selectedItems的列表,並設置(父級)的狀態
    • 觸發列表的重新呈現,並將新的selectedItems作爲道具
  • +1

    是的。謝謝@wintvelt。我做了同樣的工作,按預期工作。 –

    相關問題