文章中英模式
布魯斯前端React面試題目 - 解釋 React Key 的用途
深入解析React中key屬性的作用、如何正確使用key、常見錯誤以及對性能的影響。了解為何不應使用索引作為key,key如何協助React識別元素變化,以及React協調算法與key的關係。
文章中英模式

懶得看文章?那就來看影片吧
React Key 的作用是什麼?
在React中,key 是一個特殊的props,主要用於幫助React識別列表中的元素。它就像是每個元素的「身分證」,讓React能快速找出哪些元素有變化。
Key的主要作用:
- 1. 提升DOM更新效率
- 2. 保持元件狀態不丟失
- 3. 避免不必要的重新渲染
- 4. 確保列表元素的唯一性
Key 與 React 渲染列表的關係
當React渲染列表時,它需要知道哪些元素需要更新、新增或刪除。
沒有key:React只能按位置比較
原列表:
位置0: 蘋果
位置1: 香蕉
位置2: 橘子
新增「芒果」到開頭:
位置0: 蘋果→芒果 (更新)
位置1: 香蕉→蘋果 (更新)
位置2: 橘子→香蕉 (更新)
位置3: 新增橘子
有key:React可按身分比較
原列表:
key="a": 蘋果
key="b": 香蕉
key="c": 橘子
新增「芒果」到開頭:
key="m": 新增芒果
key="a": 蘋果 (不變)
key="b": 香蕉 (不變)
key="c": 橘子 (不變)
使用索引作為key的問題
⚠️ 當列表順序會有所改變時,索引key會導致不必要的DOM更新:
// 如果列表會更新,不好的做法
{items.map((item, index) => (
<Item key={index} data={item} />
))}
// 好的做法
{items.map(item => (
<Item key={item.id} data={item} />
))}Key 也可被用於強制重新創建組件
元件的實例、狀態和DOM與其key密切相關。當key改變時,即使元件類型相同,React也會:
- 1. 完全卸載舊元件實例(觸發
useEffect的清理函數) - 2. 創建新元件實例(重新觸發
useEffect) - 3. 重置元件的所有內部狀態
- 4. 重建DOM節點
這種行為可以被有意利用來強制重置元件狀態:
// 使用key重置表單元件
function ResetableForm({ formData, resetKey }) {
return (
<Form
key={resetKey} // 當resetKey改變時,整個Form元件會重置
initialValues={formData}
>
{/* 表單內容 */}
</Form>
);
}
// 使用案例
function ProfileEditor() {
const [user, setUser] = useState(null);
const [resetCounter, setResetCounter] = useState(0);
// 當用戶切換時,我們可以透過改變key來重置表單
return (
<div>
<UserSelector onSelect={setUser} />
<ResetableForm
formData={user}
resetKey={user?.id || resetCounter}
/>
<button onClick={() => setResetCounter(c => c + 1)}>
重置表單
</button>
</div>
);
}Key 的最佳實踐
選擇正確的key
- 優先使用穩定、唯一的ID: 資料通常有固有的ID,如資料庫主鍵、UUID等
- 其次考慮內容雜湊: 如果沒有ID,可基於內容生成雜湊值
- 避免使用隨機值: 每次渲染產生的隨機key會導致所有元件重新渲染
- 最後才考慮索引: 只在項目穩定不變、沒有重新排序時使用索引
常見錯誤
// ❌ 錯誤:使用索引作為可變列表的key
{items.map((item, index) => (
<TodoItem key={index} item={item} />
))}
// ❌ 錯誤:使用隨機值或時間戳作為key
{items.map(item => (
<TodoItem key={Math.random()} item={item} />
))}
// ✅ 正確:使用固有ID
{items.map(item => (
<TodoItem key={item.id} item={item} />
))}
// ✅ 替代方案:結合索引和穩定識別屬性
{items.map((item, index) => (
<TodoItem key={`${item.name}-${index}`} item={item} />
))}🔥 常見面試題目
(一) React中為什麼需要key?不提供key會有什麼後果?
解答: React用key來識別列表中的元素,就像每個人的身分證號碼。有了key,React才能:
- 1. 知道哪些元素變了、新增了或刪除了
- 2. 決定能否重用元素而不是重建
- 3. 正確保留元素狀態
沒有key的後果:
原始列表
刪除A後
沒提供key時,React默認用索引,這在列表變動時會導致:
- 1. 性能下降(過度重建DOM)
- 2. UI混亂(如錯誤的選中狀態)
- 3. 狀態錯亂(如輸入框內容跑錯位置)
(二) 為什麼不建議使用索引作為key?什麼情況下可以使用?
解答: 索引只是位置編號,不代表項目本身。當列表變動時,同一索引可能對應不同項目:
// 原列表:索引與項目的對應
[0: 蘋果, 1: 香蕉, 2: 橘子]
// 刪除蘋果後:同樣的索引現在對應不同項目!
[0: 香蕉, 1: 橘子]這會導致:
- 1. 元件被不必要地重建
- 2. 表單輸入值跑位
- 3. 狀態混亂
只有在這些條件全部滿足時才能用索引:
- 1. 列表永遠不會重排序
- 2. 不會添加/刪除項目
- 3. 項目沒有ID
- 4. 元件沒有狀態
(三) 如何正確生成key值?有哪些常見策略?
解答: 好的key應該是穩定且唯一的,按優先順序:
- 數據ID:最理想的選擇
<Item key={user.id} /> - 內容雜湊:當沒有ID時
<Item key={hash(item.content)} /> - 生成ID:初始化時創建
// 初始化時添加ID const data = items.map(i => ({...i, id: uuid()}))