React 面試有兩題看起來很基礎,但很容易看出你是不是真的理解 React 的運作方式:
- React Key 為什麼重要?
useEffect的 dependency array 為什麼重要?
這兩題都跟「React 怎麼判斷變化」有關。
React Key 為什麼重要?
React 在 render list 時,需要知道每個 item 對應到哪個舊的 element。
key 就是用來幫 React 辨識 list item 身份的。
{todos.map((todo) => (
<TodoItem key={todo.id} todo={todo} />
))}如果 key 穩定,React 就能知道:
todo id=1 還是原本那個 todo
todo id=2 被刪除了
todo id=3 移到前面了面試可以這樣回答:
key 是 React 在 list diff 時用來辨識元素身份的值。穩定的 key 可以幫助 React 正確重用或移除 DOM 和 component instance,避免狀態對錯 item,也能減少不必要的重建。
為什麼不建議用 index 當 key?
如果列表永遠不會新增、刪除、排序,用 index 當 key 不一定會立刻出事。
但只要列表順序會變,index 就會變得危險。
假設原本:
index 0 → Alice
index 1 → Bob
index 2 → Cindy刪除 Alice 後:
index 0 → Bob
index 1 → CindyReact 看到 key 0 還存在,可能會把原本 Alice 的 component instance 拿去渲染 Bob。這時如果 row 裡有 local state,例如 input 值、展開狀態、動畫狀態,就可能對到錯的人。
index 當 key 可能造成什麼問題?
常見問題:
- input 的值跑到另一列
- checkbox 勾選狀態錯位
- 展開 / 收合狀態錯位
- 動畫異常
- component 沒有照預期 remount
- React diff 判斷不準,造成不必要更新
不好的寫法:
{users.map((user, index) => (
<UserRow key={index} user={user} />
))}比較好的寫法:
{users.map((user) => (
<UserRow key={user.id} user={user} />
))}面試補一句:
key 最好使用資料本身穩定且唯一的 id,而不是 render 當下的位置。
useEffect dependency array 是什麼?
useEffect 的 dependency array 告訴 React:
這個 effect 依賴哪些值?哪些值變了要重新執行?
useEffect(() => {
fetchUser(userId);
}, [userId]);這代表 userId 變了,就重新抓資料。
如果 dependency array 是空陣列:
useEffect(() => {
fetchUser(userId);
}, []);effect 只會在 mount 後跑一次。即使 userId 後來變了,也不會重新執行。
漏寫 dependency 可能發生什麼問題?
1. stale closure
effect 裡讀到舊值。
useEffect(() => {
const timer = setInterval(() => {
console.log(count);
}, 1000);
return () => clearInterval(timer);
}, []);如果 count 沒放進 dependency,interval 裡可能一直印舊的 count。
2. 資料不同步
useEffect(() => {
fetch(`/api/users/${userId}`);
}, []);如果 userId 變了,畫面可能還顯示上一個使用者的資料。
3. 清理邏輯錯誤
例如 websocket、subscription、event listener 沒有在 dependency 變更時正確解除與重綁。
useEffect(() => {
socket.subscribe(roomId);
return () => {
socket.unsubscribe(roomId);
};
}, [roomId]);dependency array 不是想省就省
有時候開發者會為了「不要讓 effect 一直跑」故意漏 dependency。
這通常是在掩蓋問題。
比較好的做法:
- 把需要穩定的 function 用
useCallback - 把衍生值用
useMemo - 把不需要觸發 render 的值放
useRef - 把 effect 拆小,讓每個 effect 只處理一件事
- 確認 effect 是否真的需要存在
很多時候,其實不需要 useEffect。
如果只是根據 props / state 算出另一個值,應該直接在 render 裡算或用 useMemo,不要用 effect 同步 state。
面試回答模板
如果面試官問 key:
key 是 React 在 list diff 時用來辨識 item 身份的值。它應該穩定且唯一,通常用資料的 id。用 index 當 key 在列表新增、刪除、排序時可能讓 component state 對錯資料,例如 input 值或 checkbox 狀態跑到另一列。
如果面試官問 dependency array:
dependency array 是告訴 React effect 依賴哪些值。漏寫 dependency 可能造成 stale closure、資料不同步、subscription 清理錯誤。我的原則是讓 dependency 誠實反映 effect 用到的外部值,如果造成 effect 太常跑,會回頭調整程式結構,而不是刻意漏寫。
這兩題都不是背 API,而是在看你能不能理解 React 如何維持元件身份與同步副作用。