logo-yuki

Yuki

Post

とうこう

React 為什麼要 immutable?事關 React 是怎麼 re-render 畫面的。

React 面試八股題。

2 分鐘
✦interview-preparation

React 是怎麼 re-render 畫面的,你知道嗎?

就是它會去比較 prev state 跟 current state 呀!兩個不同就 re-render 囉。(欸嘿,這面試題太簡單啦!我應該回答的很好。)

喔?那你說說看,它怎麼比較新舊 state 的呢?

就是 `useState()` 裡面有提供 callback function 呀! 寫一個 `(prev) => { // ... }` 這樣就能比較了。(經典的 counter 不會動該怎麼修的題目嘛!我知道!)

嗯嗯…。(鍵盤疾打,在面試官筆記內輸入「這位面試者似乎還停留在只會「使用 React」的程度,對原理瞭解得較淺。」)

…。(啊咧咧!怎麼氣氛好像挺微妙的!可是我答得很好呀?)

先備知識

這些觀念還不清楚的要先看唷。

先承認,開頭的小劇場就是我真實發生過的事。

每次呼叫 setState(),React 會用 Object.is() 比較新舊 state。

對 Primitive 來說這沒問題,值不一樣就是不一樣。 但對 Object / Array,Object.is 比的是記憶體位址,不是內容。

js
const a = { name: 'Yuzu' };
const b = a;
b.name = 'Mochi';

Object.is(a, b); // true,位址一樣,React 認為沒變

直接 mutate畫面不更新

const [cat, setCat] = useState({ name: 'Yuzu' });

// ❌ 錯誤寫法
const rename = () => {
  cat.name = 'Mochi'; // 直接改,位址沒變
  setCat(cat);        // React 比較後:一樣,不 re-render
};

回傳新物件畫面正確更新

const [cat, setCat] = useState({ name: 'Yuzu' });

// ✅ 正確寫法
const rename = () => {
  setCat({ ...cat, name: 'Mochi' }); // 新物件,位址不同
};

spread 建立一個新物件位址不同Object.is 回傳 falseReact 知道 state 變了才會 re-render

Array 同理 mapfilter[...arr] 而不是直接 push splice

// ❌
list.push(newItem);
setList(list);

// ✅
setList([...list, newItem]);