軟體工程師職涯升級計畫啟動!立即預約職涯諮詢、履歷健檢或模擬面試👈,為您的加薪做好準備!
React 的 useEffect
是管理副作用(side effects)不可或缺的 Hook,但當你在同一個 component 中使用多個 useEffect
且包含非同步操作時,你可能會對它的執行順序產生疑問。
這篇文章將透過實例,說明 useEffect
的執行邏輯、非同步請求的順序,以及如果需要等所有 API response 都完成後再 render 畫面,該如何處理。
💡 問題情境:三個 useEffect
+ 非同步請求
jsx
複製編輯useEffect(() => {
console.log("1");
const fetchData = async () => {
try {
const result1 = await axios.get(url);
console.log(result1);
} catch (error) {
// error handle
}
};
fetchData();
}, []);
useEffect(() => {
console.log("2");
const fetchData = async () => {
try {
const result2 = await axios.get(url);
console.log(result2);
} catch (error) {
// error handle
}
};
fetchData();
}, []);
useEffect(() => {
console.log("3");
const fetchData = async () => {
try {
const result3 = await axios.get(url);
console.log(result3);
} catch (error) {
// error handle
}
};
fetchData();
}, []);
console.log("4");
🔍 執行順序預測與結果
當這段程式執行時,console log 的順序將會是:scss
複製編輯4
1
2
3
(result1 或 result2 或 result3)
🧠 原因解析:
console.log("4")
是在 render 階段同步執行,會優先被執行。- 三個
useEffect
都設為[]
(只在 mount 時執行),React 會依照它們在程式碼中的宣告順序執行。 - 每個
useEffect
中的fetchData
是非同步的,不會阻塞下一個useEffect
的執行。 - 三個
axios.get()
的回傳順序不保證,會根據 API 回應速度而定。
🚧 驚訝點:非同步請求不影響 useEffect 執行順序
這段邏輯的關鍵點在於:
即使第一個 useEffect
中的 API 還沒回來,第二、第三個 useEffect
依然照順序執行。
這代表:
useEffect
是依序排程副作用,但不會等待前一個async
動作完成後才進行下一個。
✅ 若要等待三個 API 都完成再繼續:使用 Promise.all
有些情況下,我們需要確保所有請求完成後再執行下一步(例如:組合顯示資料、切換 loading 狀態等)。此時應該整合三個請求為一個 Promise.all
:
jsx
複製編輯useEffect(() => {
const fetchData = async () => {
try {
const [result1, result2, result3] = await Promise.all([
axios.get(url1),
axios.get(url2),
axios.get(url3)
]);
console.log(result1, result2, result3);
// ✅ 所有資料準備完成後可更新畫面或取消 loading
} catch (error) {
// error handle
}
};
fetchData();
}, []);
Promise.all
會同時發出所有請求,並在全部都成功回應後才進入try
區塊的下一行。- 若其中任一請求失敗(例如 404),將直接進入
catch
區塊。
⚠️ 小補充:try...catch
不處理 HTTP 內部錯誤狀態
Axios 的 catch
只會捕捉非 2xx 的 HTTP 錯誤(如 404、500),但若 API response 是 200,卻仍表示失敗(如 status: "error"
),那就需要你自行處理:
js
複製編輯if (result.data.status === "ok") {
// success logic
} else if (result.data.status === "error") {
// handle API internal error
}
📌 小結
- 多個
useEffect
在同一個 component 中,會依照宣告順序依序執行,但其中的非同步邏輯彼此不會等待。 - 非同步資料的回傳順序無法保證,需使用
Promise.all
或其他控制流程方法來同步。 - 若有複數 API 的成功與失敗狀態需處理,記得區分 HTTP 錯誤與業務邏輯錯誤。
📚 延伸閱讀建議
🧠 有任何想法或補充,歡迎留言討論,也可以把這篇文章分享給剛接觸 useEffect
的朋友,一起解開 React 非同步流程的迷霧!