此文是我作為 React 工程師 (Junior) 的學習記錄(更新至 2026/03/12),歡迎各位大大指正。
上週面試時,遇到一個有趣的考題。面試官給了這段程式碼,請我找出這段程式碼有什麼問題。
function Form() {
const [firstName, setFirstName] = useState('Taylor');
const [lastName, setLastName] = useState('Swift');
const [fullName, setFullName] = useState('');
useEffect(() => {
setFullName(firstName + ' ' + lastName);
}, [firstName, lastName]);
// ...其他程式碼
}
(此段程式碼來源於React官網)
老實說,第一眼看上去只覺得程式看起來可以執行,邏輯上也沒問題呀?但其實,這是一種反模式(Anti-pattern)。
這段程式碼主要存在著兩個問題:
- 因為 React 渲染機制的關係,當我們修改 firstName 時,舊組件會先以舊的 fullName 渲染一次,再透過
useEffect進行 state 更新,渲染成新的 fullName 。 - 在後續的程式維護,我們被迫多維護
useEffect的依賴,假設後續邏輯有變,可能會不小心忘記維護。
- 因為 React 渲染機制的關係,當我們修改 firstName 時,舊組件會先以舊的 fullName 渲染一次,再透過
在 React 官方文件 You Might Not Need an Effect 中建議:如果某個值可以從現有的 props 或 state 計算出來,就不應該將其放入 state。
我們應該直接在渲染期間計算:
function Form() {
const [firstName, setFirstName] = useState('Taylor');
const [lastName, setLastName] = useState('Swift');
// 直接在渲染期間計算
const fullName = firstName + ' ' + lastName;
// ...其他程式碼
}
(此段程式碼來源於React官網)
useEffect 應該用於「處理副作用」,例如:操作 DOM、訂閱事件、或是呼叫 API 等與外部系統同步的行為。
如果是為了根據 A 狀態去更新 B 狀態,能直接推導出來的話,就讓它保持簡單吧!










