2016-02-09 31 views
4

這是因爲處理state變量具有自己的功能。有兩種方法我可以想到。一種是通過調用狀態函數直接改變this.state(當然,我知道它是不鼓勵的),然後調用forceUpdate()並處理它帶來的問題。另一個是做回調函數。哪一種是正確的?forceUpdate()與this.setState()與回調

下面是我正在談論的一個例子。我正在使用Vis.js,他們的DataSet對象允許您將數據添加到現有數據集 - 例如節點和邊。

addDataToGraph: function(data) { 
    // Is this the proper way to do something like this? 
    this.state.graphData.nodes.add(nodes); 
    this.state.graphData.edges.add(edges); 
    this.forceUpdate(); 

    // Or is this the right way - the question I am posing here 
    this.setState({ 
     currentChunk: data.currentChunk, 
     totalChunks: data.totalChunks 
    }, function() { 
     this.state.graphData.nodes.add(data.nodes); 
     this.state.graphData.edges.add(data.edges); 
    }.bind(this)); 
    } 
+2

我會用第二種方法。直接操縱狀態繞過了'setState'機制帶來的許多性能優勢,而且您可能會遇到邊緣情況並且將來會有事情中斷。 – rossipedia

回答

4

你絕對不應該改變this.state或其中的任何東西。從React Component API docs

不要直接改變this.state,因爲之後調用setState()可能會替換您所做的突變。將this.state視爲不可變的。

setState()不會立即改變this.state,但會創建暫掛狀態轉換。調用此方法後訪問this.state可能會返回現有值。

無法保證對setState的調用進行同步操作,並且可能會調用調用以提高性能。

setState()將始終觸發重新渲染,除非在shouldComponentUpdate()中實現了條件渲染邏輯。如果正在使用可變對象,並且該邏輯不能在shouldComponentUpdate()中實現,則僅當新狀態與先前狀態不同時調用setState()才能避免不必要的重新呈現。

即使你的第二個例子在這裏不正確,因爲你仍然在變異this.state。第二個參數僅僅是狀態更新時的回調。你想要做的是以某種方式獲得新的對象,並給予setState。對Vis.js不熟悉,這看起來有些棘手,因爲它似乎沒有任何操作返回完全新/不可變的數據集。甚至沒有複製或克隆操作。它看起來就像你有一個全新的vis.DataSet每次實際上使從原來的添加數據,然後添加新數據,然後this.setState({ graphData: newGraphData, ... })

最終這將可能是做「純粹」和正確的方法這個。

所有這一切,並與一個大的YMMV警告 - 因爲沒有明顯的方式來對待vis.DataSet s是不可變的,你可能只需要第一個選項。

採取警告的是第一部分中的文檔:

調用的setState()之後可以更換突變所做

會在這種情況下會發生什麼?沒有什麼,因爲你的狀態中的實際對象是可變的,它只是永遠的一個引用。如果React'替換它',它將會自己替換它。換句話說,只要你從不用一個全新的數據集調用setState,它就不會被意想不到的事情所取代。

這裏的一個大問題是,調用forceUpdate會強制重新渲染,而這可能會很慢。但它主要聽起來像你想它重新渲染,無論如何當該功能被稱爲,所以... 務實地說你可能確定:)

0

要改變組件的狀態,我們應該總是使用this.setState(),因爲它告訴React組件狀態中的某些內容發生了變化,然後React將負責以高性能的方式重新渲染。然而,我們也可以通過使用this.state.yourProperty = somethingNew來改變狀態對象,但是我們絕不應該這樣做,因爲它太顯示了,而且React沒有意識到我們的狀態變化,所以我們必須明確地觸發這個狀態,通過致電render.forceUpdate()。一個很好的例子使用this.forceUpdate是與其他庫如D3.js.的集成。 D3有它自己的數據集,所以假設如果D3數據集中的某些內容發生變化,那麼它需要告訴React'嘿! React我改變了我的一些東西,現在我需要重新渲染',因此D3會回調出使用this.forceUpate()