Câu hỏi: "Có nên dùng Early Return (return sớm) không?" Câu trả lời: CÓ. Hãy dùng nó như một tôn chỉ.
1. Vấn đề của Nested If (Arrow Code)
Khi bạn dùng if-else lồng nhau, code của bạn sẽ có hình dáng mũi tên (Arrow Code).
// ❌ HARD TO READ
function UserProfile({ user, isLoading, hasError }) {
if (!isLoading) {
if (!hasError) {
if (user) {
if (user.isActive) {
return <div>Welcome {user.name}</div>;
} else {
return <div>User inactive</div>;
}
} else {
return <div>No user</div>;
}
} else {
return <div>Error</div>;
}
} else {
return <Spinner />;
}
}Não bộ con người hoạt động như một ngăn xếp (stack). Mỗi lần thấy dấu mở ngoặc {, não bạn phải ghi nhớ ngữ cảnh đó. Nested 4 tầng = Não phải nhớ 4 điều kiện cùng lúc.
2. Giải pháp: Early Return (Code phẳng)
Hãy xử lý các trường hợp ngoại lệ (Loading, Error, Empty) trước và return ngay lập tức.
Code chính (Happy Path) sẽ nằm ở cuối cùng và không bị thụt lề.
// ✅ EASY TO READ
function UserProfile({ user, isLoading, hasError }) {
// 1. Guard Clauses (Chặn cửa)
if (isLoading) return <Spinner />;
if (hasError) return <ErrorView />;
if (!user) return <EmptyState />;
// 2. Happy Path (Code chính ở ngoài cùng)
if (!user.isActive) return <InactiveView />;
return <div>Welcome {user.name}</div>;
}Lợi ích:
- Cognitive Load thấp: Đọc xong dòng Loading là quên nó đi được rồi. Không cần nhớ "cái else của loading nằm ở đâu nhỉ?".
- Dễ debug: Lỗi ở đâu return ở đó.
3. Cạm bẫy: Render có điều kiện trong JSX
Trong JSX, ta hay dùng toán tử 3 ngôi (Ternary). Nhưng nếu lồng nhau thì thảm họa.
// ❌ Ternary Hell
return (
isLoading ? <Spinner /> : hasError ? <Error /> : user ? <Card /> : <Empty />
);
// Đừng làm thế này. Hãy tách ra biến hoặc Early Return bên trên.4. Khi nào KHÔNG nên Early Return?
Trong React, có một quy tắc vàng: Hook phải được gọi theo thứ tự cố định. Bạn KHÔNG ĐƯỢC Early Return trước khi gọi Hook.
// ⛔️ SAI LẦM CHẾT NGƯỜI
function Profile({ id }) {
if (!id) return null; // ❌ Early Return ở đây
const { data } = useQuery(id); // ❌ Hook này có thể không được gọi -> React Crash
return <div>{data.name}</div>;
}
// ✅ SỬA LẠI
function Profile({ id }) {
const { data } = useQuery(id, { enabled: !!id }); // Hook luôn được gọi
if (!id) return null; // ✅ Early Return sau khi gọi Hook
if (!data) return <Spinner />;
return <div>{data.name}</div>;
}Kết luận
- Luôn ưu tiên Early Return để đưa logic về dạng phẳng.
- Xử lý hết các trường hợp "xấu" (Loading/Error/Null) ở đầu hàm.
- Cẩn thận với React Hooks rules.