我開發 React 應用程式已經有幾年了,我經歷了無數的錯誤,這些錯誤減慢了專案的開發速度。
React 是建立動態使用者介面的最受歡迎的程式庫之一,但它的靈活性也會導致新開發人員犯下某些常見錯誤。
本指南涵蓋了開發人員在 React 中最容易犯的錯誤,並提供了可操作的技巧來編寫更好、更有效率的程式碼。
讓我們開始吧!
在繼續之前,讓我們先編寫我們的 React 元件,該元件應該顯示項目列表,以及新增或刪除一個項目:
import { useState } from "react"; const Home = (props) => { const [items, setItems] = useState(['item1', 'item2']); const [itemToAdd, setItemToAdd] = useState(''); function wrongHandleAddItem(item) { items.push(item); setItems(items); } function goodHandleAddItem(item) { if (item.length === 0) return; const newArray = [...items, item]; setItems(newArray); setItemToAdd(''); } function removeItem(item) { const itemIndex = items.indexOf(item); if (itemIndex !== -1) { const newArray = [...items]; newArray.splice(itemIndex, 1); setItems(newArray); } } return ( <div> <p>Here, I wrote two different methods to add an item in the items state array. Let's break it down together:<br> </p> <pre class="brush:php;toolbar:false">function wrongHandleAddItem(item) { items.push(item); setItems(items); }
此方法所做的第一件事是呼叫推送數組函數,旨在將元素添加到數組中。
第二件事是呼叫 setItems 將變更套用到狀態變數。
但是,如果您嘗試執行此程式碼,它將無法運作❌
這段程式碼違反了一個非常重要的 React 規則:改變狀態。
React 依靠狀態變數的身份來判斷狀態何時會改變。當我們將項目推入數組時,我們並沒有更改該數組的標識,因此 React 無法判斷該值已更改並重新渲染該數組。
以下是修復方法 ✅ :
function goodHandleAddItem(item) { if (item.length === 0) return; const newArray = [...items, item]; setItems(newArray); setItemToAdd(''); }
在此方法中,我使用展開運算子建立了一個新陣列...允許使用專案內容實例化新陣列。第二個參數用於新增內容(此處為 item)。
最後一步是呼叫 setItems 方法來驗證變數項目的新狀態 ✅
每個 React 開發者在他們的開發過程中可能至少見過一次這個錯誤。
發生這種情況的最常見方式是映射資料時。以下是此違規行為的範例:
items.map((item) => ( <div> {item} <button onClick={() => removeItem(item)}>-</button> </div> ))}
當我們想要渲染一個元素陣列時,我們需要為 React 提供更多的上下文以允許它識別每個項目。在最好的情況下,它必須是唯一識別碼。
這是解決此問題的快速方法,但這並不是最佳方法:
items.map((item, index) => ( <div key={index} > {item} <button onClick={() => removeItem(item)}>-</button> </div> ))}
當您獲得 React 經驗並了解它如何更好地工作時,您將能夠根據您的情況判斷它是否可以。
為了使其完美,您可以使用 uuid 產生器,例如 crypto.randomUUID() 並將其作為物件儲存到項目清單中,如下所示:
const newItemToAdd = { id: crypto.randomUUID(), value: item }; const newArray = [...items, newItemToAdd]; setItems(newItems);
並在渲染過程中如下使用它:
items.map((item, index) => ( <div key={item.id} > {item.value} <button onClick={() => removeItem(item)}>-</button> </div> ))}
現在一切都很完美✅
假設我們有一個函數需要在掛載時從 API 取得一些資料。我們將使用 useEffect 鉤子,並且我們想要使用 wait 關鍵字。
讓我們檢查一下第一次嘗試:
如您所知,await 關鍵字需要位於標有 async 關鍵字的函數中:
import { useState } from "react"; const Home = (props) => { const [items, setItems] = useState(['item1', 'item2']); const [itemToAdd, setItemToAdd] = useState(''); function wrongHandleAddItem(item) { items.push(item); setItems(items); } function goodHandleAddItem(item) { if (item.length === 0) return; const newArray = [...items, item]; setItems(newArray); setItemToAdd(''); } function removeItem(item) { const itemIndex = items.indexOf(item); if (itemIndex !== -1) { const newArray = [...items]; newArray.splice(itemIndex, 1); setItems(newArray); } } return ( <div> <p>Here, I wrote two different methods to add an item in the items state array. Let's break it down together:<br> </p> <pre class="brush:php;toolbar:false">function wrongHandleAddItem(item) { items.push(item); setItems(items); }
不幸的是,這不起作用,我們收到此錯誤訊息:
function goodHandleAddItem(item) { if (item.length === 0) return; const newArray = [...items, item]; setItems(newArray); setItemToAdd(''); }
這裡是修復:在 useEffect 掛鉤中建立一個單獨的非同步函數 ✅
items.map((item) => ( <div> {item} <button onClick={() => removeItem(item)}>-</button> </div> ))}
了解 async 關鍵字的意思很重要:
它不回傳物件 json,它傳回一個解析物件 json 的 Promise。
這實際上是一個問題,因為 useEffect 不應該返回 Promise。它期望我們要么不返回任何內容(就像上面的那樣),要么返回一個清理函數。清理功能很重要,超出了本指南的範圍,但這裡可以使用它:
items.map((item, index) => ( <div key={index} > {item} <button onClick={() => removeItem(item)}>-</button> </div> ))}
讓我們回到狀態管理,看看新開發人員常犯的另一個有趣的錯誤。這將幫助我們更好地理解 React 狀態。
讓我們用 goodHandleAddItem 方法來說明這一點:
const newItemToAdd = { id: crypto.randomUUID(), value: item }; const newArray = [...items, newItemToAdd]; setItems(newItems);
執行此程式碼時,我們可以看到控制台沒有記錄我們期望的結果。
問題是:狀態變數的setter 函數是非同步。
當我們呼叫 setItems 方法時,我們實際上是在安排更新,而不是分配變數。
這裡是修復:我們已經知道 newArray 變數的變數內容應該是什麼。這意味著要使用我們想要作為 items 變數內容的數據,即使在 setItems ✅ 之後,我們也需要 使用變數 newArray
來代替最後一篇也是關於React狀態管理的,看完這篇指南你就會成為專家了! ?
使用 React Hooks 時的一個常見陷阱是濫用過時的狀態資料。當我們在連續狀態更新中直接引用狀態變數時,可能會發生這種情況。正如我們在上一個錯誤中看到的,狀態更新可能是非同步的,這意味著狀態變數在連續呼叫中引用時可能不會反映最新值。
讓我們用一個全新的例子來讓事情變得更清楚,眾所周知的計數器:
items.map((item, index) => ( <div key={item.id} > {item.value} <button onClick={() => removeItem(item)}>-</button> </div> ))}
以上用法是錯誤的。事實上,count 是在 setCount 呼叫中直接引用的。在事件處理程序和生命週期方法中,狀態更新可以批量進行,並且都使用與計數相同的初始值,這將導致最終狀態不正確。
我們可以使用另一種形式的 setCount 來讓事情正常運作:更新函數。 updater 函數將先前的狀態作為參數並傳回新的狀態,因此每次連續的更新都會具有正確的值,從而防止出現不必要的行為。
使用方法如下:
import { useState } from "react"; const Home = (props) => { const [items, setItems] = useState(['item1', 'item2']); const [itemToAdd, setItemToAdd] = useState(''); function wrongHandleAddItem(item) { items.push(item); setItems(items); } function goodHandleAddItem(item) { if (item.length === 0) return; const newArray = [...items, item]; setItems(newArray); setItemToAdd(''); } function removeItem(item) { const itemIndex = items.indexOf(item); if (itemIndex !== -1) { const newArray = [...items]; newArray.splice(itemIndex, 1); setItems(newArray); } } return ( <div> <p>Here, I wrote two different methods to add an item in the items state array. Let's break it down together:<br> </p> <pre class="brush:php;toolbar:false">function wrongHandleAddItem(item) { items.push(item); setItems(items); }
記錄計數內容現在指示正確的值✅
避免這些常見錯誤將使您開發出更高效能的 React 應用程式並掌握狀態管理!
希望這份指南對您有幫助,並祝您編碼愉快!
作為新的或已確認的 React 開發人員,如果您喜歡本指南,請留下一個讚?
很快再見!
以上是React 開發中最常見的錯誤以及如何避免它們 ⚛️的詳細內容。更多資訊請關注PHP中文網其他相關文章!