Mục lục

Clean Code Patterns: Early Return & Guard Clauses

Tại sao bạn nên dùng Early Return thay vì if-else lồng nhau? Kỹ thuật làm phẳng code (Flattening) để giảm tải nhận thức (Cognitive Load). Khi nào KHÔNG nên Early Return?

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).

tsx:
// ❌ 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ề.

tsx:
// ✅ 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.

tsx:
// ❌ 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.

tsx:
// ⛔️ 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.
Quảng cáo
mdhorizontal