2015-08-13 168 views
2

我想不出我在做什麼錯在這裏。我有一個Event觸發一個函數來改變幾個值的狀態,這樣我就可以觸發一個API調用;然而,第一次運行的功能狀態不會改變。第二次函數運行時,將設置上一次運行的狀態更改。什麼可能造成這種延誤?狀態不立即更新ReactJS

因此,大家可以看到下面handleFilterChange從事件接收的值,我可以確認正在接收正確的價值觀;然而,如果我在設置後立即檢查狀態值,我可以看到它是未定義的。當事件再次發生時;然而,我可以看到原來的狀態變化現在已經發生,但第二個沒有。那麼爲什麼setState必須被調用兩次才能真正設置狀態?

var GridView = React.createClass({ 
    getInitialState: function() { 
    window.addEventListener("scroll", this.handleScroll); 
    return { 
     data: [], 
     page: 0,  //for pagination 
     loadingFlag: false, 
    }; 
    }, 

    getMainFeed: function() { 

... 

}, //end function 
getFilteredItems: function() { 
    ... 

}, //end function 
    componentWillMount: function() { 

    }, 
    listenForFilterChange: function() { 
    window.addEventListener("selectedFilterChange", this.handleFilterChange, false); 
    }, 
    componentWillUnmount: function() { 
    window.removeEventListener("selectedFilterChange", this.handleFilterChange, false); 
    }, 
    handleFilterChange: function(filter) { 
    //alert(filter.detail.filterType); 
    //Convert Data for getFilteredItems 
    //(EventType, Category, Buy, Inspiration) { 
    switch (filter.detail.filterType) { 
    //alert(filter.detail.filterType); 
    case 'category': 
     this.setState({ 
     itemCategory: filter.detail.filterSelected, 
     }); 
     break; 
    case 'event': 
     this.setState({ 
     eventType: filter.detail.filterSelected, 
     }); 
     break; 
    case 'type': 
     if (0){ 
     this.setState({ 
      filterBuy: 1, 
      filterInspiration: 0, 
     }); 
     } 
     if (1){ 
     this.setState({ 
      filterBuy: 0, 
      filterInspiration: 1, 
     }); 
     } 
     if (2){ 
     this.setState({ 
      filterBuy: 1, 
      filterInspiration: 1, 
     }); 
     } 
     break; 
    case 'trending': 
     this.setState({ 
     itemCategory: filter.detail.filterSelected, 
     }); 
     break; 
    } 

    this.getFilteredItems(); 
}, 
    componentDidMount: function() { 
    this.listenForFilterChange(); 
... 
    }, 
    handleScroll:function(e){ 
... 
    }, 
    componentDidUpdate: function() { 
... 
    }, 
    render: function() { 
     return (
     <div id="feed-container-inner"> 
      <GridMain data={this.state.data} /> 
     </div> 

    ); 
    } 
    }); 

回答

2

setState是異步的,所以變化不會立即以狀態所反映:

的setState()不會立即發生變異this.state而是創建一個 待定狀態轉換。調用 方法後訪問this.state可能會返回現有值。

如果您需要根據狀態更改確認狀態或執行邏輯,請使用here中所述的回調參數。

+0

謝謝@David。我沒有意識到這一點,現在這變得更有意義。 –

0

setState不必被調用兩次。讀你的代碼,我不能推斷出這正是錯誤的,但我可以告訴這個:

  1. CONSOLE.LOG您在狀態呈現功能,如果你想知道什麼是在裏面。
  2. 再次檢查什麼在你的事件(什麼情況下被觸發,如果它真的觸發)。 3.檢查,如果另一個函數(另一種的setState)未覆蓋的狀態要在handlefilterChange設置。

我敢打賭,你的過濾器沒有收到正確的價值觀,首先接收不確定filter.detail.filterSelected然後又一個定義...... 檢查什麼在filter.detail.filterSelected我的評論看你只檢查filter.detail.filterType

反正你的問題是不是由於對setState但是從你的資料我敢肯定。

讓我知道這是否有助於

+0

弗朗索瓦,我已經做了這些檢查,原來的問題是,'setState'是異步的,所以我必須使用回調函數。再次感謝你的幫助。 –

+0

好的,在渲染的console.log會有效,但比爾沃爾特斯的答案給出了爲什麼和更準確的原因。 –