2017-08-30 61 views
0

考慮一個編輯框。用戶鍵入一些文本。上附着有按鍵處理程序,它確實是這樣的:反應事件處理

setState({echo: this.state.echo + event.char}) 

是否有可能在初始狀態{echo: 「」},用戶鍵入「A」,然後「B」,陣營電話onKeyPress(「a」),這就要求setState({echo: 「a」}),和那麼 - setState之前實際上是由React - React calls onKeyPress(「b」)應用?

你看到一個問題,對吧? OnKeyPress(「b」)會看到同樣的老狀態{echo: 「」}OnKeyPress(「a」)做,並會發出setState({echo: 「」+「b」}),這是setState({echo: 「b」}) - 而我們顯然是想{echo: 「ab」}

  • 我的測試表明我的第二個事件處理程序不會被調用之前,首先setStat e是完全處理。但是一些測試可能存在,不像一些記錄在案的合同。
  • 我意識到這個問題有解決方案,就像使用表格setState(state => …)
  • 但我仍想知道:這種情況是否可能。也許合成事件處理程序只能在所有待處理的setState處理(由前一個處理程序引起)完成時才被執行?如果是這樣,我可以在哪裏閱讀一些證明?某些手冊中的特定位置或Web上發佈的合格答案...或者,也可能是相反的 - 這種保證不存在(但是,如果情況如此,setState的「簡單」形式肯定會導致錯誤並且他們不應該允許這種形式)。
+2

你是否看到'setState'也接受一個具有前一狀態的函數? –

+0

「我意識到這個問題有解決方案,就像使用表單setState(state => ...)」 –

回答

-1

由於這是我第二次對類似問題沒有明確答案,所以我只能推斷出至少有上述場景的理論可能性。那麼我們最好在所有情況下都遵循這個文檔,並且只使用基於函數的setState來推斷前一個狀態的下一個狀態。

+0

這讓我們走得更遠。如果任何事件處理程序中有一些邏輯根據當前狀態做出決定並設置新狀態,則最好將其全部提取到方法並將整個方法傳遞給setState。這反過來又導致了一個關於提取所有這些方法以分離攜帶所有「真實」邏輯的組件的想法,原始組件僅留下標記和存根事件處理程序(並且沒有任何狀態),具有真實的邏輯和「狀態」通過道具注入。對於表示和容器對象來說,採取或採取這種方法。 –

0

setState將始終按順序排列,但您給它的參數可以依賴於來自過去的狀態。 setState來電(例如來自您的兩個按鍵)可以被合併並在下一個週期被呼叫。

這就是您在第二點提到的解決方案存在的原因,並且是解決此問題的正確方法。你在問題中描述的方式,簡單地將狀態值和按下的鍵進行連接,正是文檔advise against

+0

授予,setState調用可以合併。但是如果知道下一次onKeyPress調用只會在處理完所有待處理的setState()調用後纔會發生,那麼這沒有問題,因爲這意味着唯一可合併的setState()調用是在同一個處理程序調用中執行的:onKeyPress calls setState然後再setState(也許間接),然後處理所有這些狀態更改(可能在合併後),然後才調用下一個onKeyPress()。不管它是否已知 - 這正是我在這裏問的問題。 –

+0

我的意思是,如果我編寫了這樣一個代碼,在同一個處理程序調用中執行多個setState調用,但不知道其異步特性,則是我的錯。你只是不這樣做:)但是無法在事件處理程序的多個後續調用中調用setState完全是另一回事。 –

+0

好的,這個地方在你提到的文檔中,它非常清楚我們不應該使用當前狀態來組成新的狀態。但是如果我們知道在調用下一個事件處理程序之前處理了所有未決的setState,或者類似的東西,那麼我們可以說在這個特定的場景中我們可以使用當前狀態。但是,當然如果不存在這樣的信息,那麼我們必須假定它是不安全的(就像文檔通常所說的那樣)。 –

0

我建議你利用組件生命週期方法componentDidUpdate和componentWillUpdate。在這些方法之間,會有一個渲染週期。這使您可以對已更改的事情做出迴應。

嘗試在捕獲密鑰時嘗試將當前按鍵字符追加到現有字符串,請嘗試在componentDidUpdate()中追加字符。

在這種情況下,您只需將當前按鍵存儲在狀態(例如currKey)中。然後在componentDidUpdate(),您可以添加這樣的事情:

componentDidUpdate(prevProps, prevState) { 
    const { currKey, echo } = this.state; 
    if (currKey !== '') { 
    this.setState({ 
     echo: echo + currKey, // append the current key to echo 
     currKey: '' // reset the current key 
    }); 
    } 
} 

的的setState這裏將觸發另一次更新一輪,然而在這一輪currKey將是空的,這意味着直到另一個關鍵是邏輯將不再執行按下。

+0

我想這可以完成,但正如我之前提到的(最近又做了一次),我意識到還有其他方法。但我在問這個特別的問題!如果知道這種情況是可能的,或者已知它是不可能的,或者沒有確定的事情是已知的。 –

+0

此外,我甚至不確定通過進一步進行狀態更改來響應componentDidUpdate是個好主意。 –

+0

我同意它可能是危險的,並且經常有林林規則警告它。但是,在這種情況下,它是安全的,不會產生無限循環。 –