關於前端開發,我最開心的事情就是總有新的東西可以學習。但我們可能一輩子都在掌握各種編程語言、庫和框架,但仍然一無所知。
因爲我們都在學習,這也意味着我們都容易犯錯誤。沒關係,我們的目的是變得更好。如果你犯了一個錯誤並從中吸取教訓,你就做得很好!但是如果你沒有學到任何新的東西,並且不斷重複犯同樣的錯誤,emmm。。。可能你的職業生涯就會停滯不前。
本着這種精神,下面是我在 CodeReview 初級開發同學時經常看到的三個錯誤。我們一起來 check 一下,然後討論如何改正它。
直接修改狀態
在更新 React 組件狀態時,最重要的是調用 setState 方法去更新,並且傳入的對象是一個新的副本,而不是直接修改之前的狀態。如果你錯誤地修改了組件的狀態,React Diff 算法將無法捕獲更改,而且你的組件也無法正確地更新。讓我們來看一個例子。
假設你有這樣的狀態:
this.state = {
colors: ['red', 'green', 'blue']
}
現在你想要給這個數組添加顏色:
// 方法1:
this.state.colors.push('yellow’)
// 方法2:
this.state.colors = [...this.state.colors, 'yellow’]
這兩種方法都是錯誤的!在更新類組件中的狀態時,必須使用 setState 方法,並且應該注意不要改變原始對象。下面是添加元素到數組的正確方法:
this.setState(prevState => ({ colors: [...prevState.colors, 'yellow'] }))
忘記了 setState 的批量更新
setState 有兩種使用方法。第一種方法是傳入一個對象作參數。第二種方法是傳入一個函數作參數。你知道這兩種方法分別應該在什麼時候使用嗎?
例如,如果你有一個可以啓用或禁用的按鈕,那麼你可能會有一個名爲 isDisabled 的狀態,其中包含一個布爾值。如果你想切換這個按鈕的狀態,你可能很會寫這樣的一段代碼:
// setState 使用一個對象作參數
this.setState({ isDisabled: !this.state.isDisabled })
那麼,這有什麼問題呢?問題在於 React 狀態更新可以批處理(batchUpdate),這意味着多個狀態更新可以在一個更新週期中發生。如果你的更新將被批處理,並且你對 isDisabled 狀態有多個更新,那麼最終結果可能不是你所期望的。
更新狀態的更正確的方法是提供前一個狀態的函數作爲參數:
this.setState(prevState => ({ isDisabled: !prevState.isDisabled }))
現在,即使你的狀態更新被批處理,並且有多個更新都在操作 isDisabled 狀態,但每個更新都依賴於正確的先前狀態,因此你總是會得到預期的結果。
類似的遞增計數器也是如此。
// 不要這樣做
this.setState({ counterValue: this.state.counterValue + 1 })
// 正確的寫法
this.setState(prevState => ({ counterValue: prevState.counterValue + 1 }))
忘記了 setState 是異步的
最後,記住 setState 是一種異步方法是很重要的。
初學者可以先理解成異步,但嚴格意義上說,需要區分條件來看。
如:在 React 內部生命週期以及事件處理函數中是異步的。
如:在 setTimeout 函數中調用 setState 卻是同步的。
舉個例子,假設我們有一個如下狀態的 React 組件:
this.state = { name: 'John' }
有一個方法更新狀態,並將新的狀態打印到控制檯上:
this.setState({ name: 'Matt' })
console.log(this.state.name)
你可能認爲打印出來的會是 Matt
,但它不會! 它會打印 John
!
這是因爲 setState 是異步的。這意味着執行到 setState 時,會把真正更新的操作放在異步隊列中去執行,但它下面的同步代碼將立即執行,所以打印出來的 state 就不是最新的。
如果你想拿到更新完成後的最新狀態,React 允許你傳一個回調函數,該函數會在更新完成後運行。
this.setState({ name: 'Matt' }, () => console.log(this.state.name))
問題解決了! 現在它可以正確地記錄 Matt
了。
總結
好了!以上就是今天給大家分享的 React 中的三個常見錯誤及其糾正方法。記住,犯錯誤是正常的,但要避免犯同樣的錯誤。你在學習、我在學習、我們都在學習。讓我們繼續學習,一起變得更好。