關于前端開發,我最開心的事情就是總有新的東西可以學習。但我們可能一輩子都在掌握各種程式設計語言、庫和架構,但仍然一無所知。
因為我們都在學習,這也意味着我們都容易犯錯誤。沒關系,我們的目的是變得更好。如果你犯了一個錯誤并從中吸取教訓,你就做得很好!但是如果你沒有學到任何新的東西,并且不斷重複犯同樣的錯誤,emmm。。。可能你的職業生涯就會停滞不前。
本着這種精神,下面是我在 CodeReview 初級開發同學時經常看到的三個錯誤。我們一起來 check 一下,然後讨論如何改正它。
在更新 react 元件狀态時,最重要的是調用 setState 方法去更新,并且傳入的對象是一個新的副本,而不是直接修改之前的狀态。如果你錯誤地修改了元件的狀态,react Diff 算法将無法捕獲更改,而且你的元件也無法正确地更新。讓我們來看一個例子。
假設你有這樣的狀态:
現在你想要給這個數組添加顔色:
這兩種方法都是錯誤的!在更新類元件中的狀态時,必須使用 setState 方法,并且應該注意不要改變原始對象。下面是添加元素到數組的正确方法:
setState 有兩種使用方法。第一種方法是傳入一個對象作參數。第二種方法是傳入一個函數作參數。你知道這兩種方法分别應該在什麼時候使用嗎?
例如,如果你有一個可以啟用或禁用的按鈕,那麼你可能會有一個名為 isDisabled 的狀态,其中包含一個布爾值。如果你想切換這個按鈕的狀态,你可能很會寫這樣的一段代碼:
那麼,這有什麼問題呢?問題在于 React 狀态更新可以批處理(batchUpdate),這意味着多個狀态更新可以在一個更新周期中發生。如果你的更新将被批處理,并且你對 isDisabled 狀态有多個更新,那麼最終結果可能不是你所期望的。
更新狀态的更正确的方法是提供前一個狀态的函數作為參數:
現在,即使你的狀态更新被批處理,并且有多個更新都在操作 isDisabled 狀态,但每個更新都依賴于正确的先前狀态,是以你總是會得到預期的結果。
類似的遞增計數器也是如此。
最後,記住 setState 是一種異步方法是很重要的。
初學者可以先了解成異步,但嚴格意義上說,需要區分條件來看。 如:在 React 内部生命周期以及事件處理函數中是異步的。 如:在 setTimeout 函數中調用 setState 卻是同步的。
舉個例子,假設我們有一個如下狀态的 React 元件:
有一個方法更新狀态,并将新的狀态列印到控制台上:
你可能認為列印出來的會是 Matt ,但它不會! 它會列印 John !
這是因為 setState 是異步的。這意味着執行到 setState 時,會把真正更新的操作放在異步隊列中去執行,但它下面的同步代碼将立即執行,是以列印出來的 state 就不是最新的。
如果你想拿到更新完成後的最新狀态,React 允許你傳一個回調函數,該函數會在更新完成後運作。
問題解決了! 現在它可以正确地記錄 Matt 了。