Skip to content
Grok

Best Practices in React Development

Component Design

  • Follow Single Responsibility Principle
tsx
// Bad: Component ที่ทำหลายหน้าที่
function UserProfile({ user }) {
  return (
    <div>
      <img src={user.avatar} />
      <button onClick={() => fetchDetails(user.id)}>Load Details</button>
      <UserDetails data={user.details} />
    </div>
  );
}

// Good: แยกเป็นคอมโพเนนต์ย่อย
function UserAvatar({ src }) {
  return <img src={src} />;
}

function ProfileActions({ userId }) {
  const handleClick = () => fetchDetails(userId);
  return <button onClick={handleClick}>Load Details</button>;
}
  • Use composition over inheritance
tsx
// ตัวอย่างการใช้งาน Composition ที่ดี
function Dashboard({ children }) {
  return (
    <div className="dashboard">
      <Header />
      <div className="content">
        {children}
      </div>
      <Footer />
    </div>
  );
}

// การใช้งาน
<Dashboard>
  <UserProfile />
  <NotificationList />
</Dashboard>;
  • Prefer small, reusable components

การออกแบบคอมโพเนนต์

  • ปฏิบัติตามหลัก Single Responsibility Principle
  • ใช้ composition แทน inheritance
  • เลือกใช้คอมโพเนนต์ขนาดเล็กที่นำกลับมาใช้ใหม่ได้

Performance

  • Use React.memo for optimization
tsx
// ควรใช้ memo เมื่อ:
// 1. คอมโพเนนต์เรนเดอร์บ่อยแต่ props ไม่เปลี่ยน
// 2. คอมโพเนนต์มีขนาดใหญ่
const HeavyComponent = React.memo(({ data }) => {
  // คำนวณอะไรที่ซับซ้อน
  return <ExpensiveRender data={data} />;
});
  • Avoid unnecessary re-renders
  • Use useCallback/useMemo appropriately
tsx
function ProductList({ products }) {
  // ใช้ useMemo เมื่อคำนวณค่าแพง
  const featuredProducts = useMemo(
    () => products.filter(p => p.isFeatured),
    [products],
  );

  // ใช้ useCallback สำหรับ event handler
  const handleAddToCart = useCallback((productId) => {
    addToCart(productId);
  }, []);

  return (
    <ul>
      {featuredProducts.map(product => (
        <ProductItem
          key={product.id}
          product={product}
          onAdd={handleAddToCart}
        />
      ))}
    </ul>
  );
}

ประสิทธิภาพ

  • ใช้ React.memo เพื่อเพิ่มประสิทธิภาพ
  • หลีกเลี่ยงการ re-render ที่ไม่จำเป็น
  • ใช้ useCallback/useMemo อย่างเหมาะสม

Code Organization

  • Group by feature, not by type
src/
  features/
    user/
      UserProfile.tsx
      useUser.ts
      userApi.ts
      components/
        UserAvatar.tsx
        UserActions.tsx
    products/
      ProductList.tsx
      useProducts.ts
      components/
        ProductCard.tsx
  • Use index files for clean imports
  • Separate concerns with custom hooks

การจัดระเบียบโค้ด

  • จัดกลุ่มตามฟีเจอร์ ไม่ใช่ตามประเภท
  • ใช้ไฟล์ index เพื่อให้การ import สะอาดขึ้น
  • แยกความรับผิดชอบด้วย custom hooks

Testing

  • Write unit tests with Jest + React Testing Library
  • Test behavior, not implementation
tsx
// ทดสอบว่าผู้ใช้สามารถล็อกอินได้
test("should allow user to login", async () => {
  render(<LoginPage />);

  // 1. หาช่อง input
  const emailInput = screen.getByLabelText("Email");
  const passwordInput = screen.getByLabelText("Password");

  // 2. จำลองการพิมพ์
  userEvent.type(emailInput, "[email protected]");
  userEvent.type(passwordInput, "password123");

  // 3. จำลองการคลิก
  fireEvent.click(screen.getByText("Login"));

  // 4. ตรวจสอบผลลัพธ์
  await waitFor(() => {
    expect(screen.getByText("Welcome back!")).toBeInTheDocument();
  });
});
  • Aim for good coverage of critical paths

การทดสอบ

  • เขียน unit test ด้วย Jest + React Testing Library
  • ทดสอบที่ behavior ไม่ใช่ implementation
  • ตั้งเป้าหมายให้ครอบคลุม critical paths

Additional Resources