React & Next.js Development Standards

evergreenLast update on Jul 9, 2026
Download .md

Project Layout

project/
├── src/
│   ├── app/              # Next.js App Router
│   ├── components/       # Reusable components
│   ├── lib/              # Utils, hooks
│   ├── hooks/            # Custom hooks
│   └── types/            # TypeScript types
├── public/
├── tests/
├── next.config.js
└── package.json

App Router

Gunakan App Router (bukan Pages Router) untuk semua project baru.

// app/users/page.tsx
export default async function UsersPage() {
  const users = await getUsers();

  return (
    <ul>
      {users.map((user) => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

Data Fetching

Gunakan TanStack Query untuk client-side fetching:

"use client";

import { useQuery } from "@tanstack/react-query";

export function UserList() {
  const { data, isLoading } = useQuery({
    queryKey: ["users"],
    queryFn: fetchUsers,
  });

  if (isLoading) return <Spinner />;
  return (
    <ul>
      {data?.map((u) => (
        <li key={u.id}>{u.name}</li>
      ))}
    </ul>
  );
}

Component Patterns

  • Functional components saja.
  • Custom hooks untuk logic reusable.
  • Server Components default, Client Components hanya untuk interaktif.
// Server Component (default)
export default function UserCard({ user }: Props) {
  return <div>{user.name}</div>;
}

// Client Component (interactive)
("use client");

export function Counter() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount((c) => c + 1)}>{count}</button>;
}

State Management

  • Local state: useState, useReducer
  • Server state: TanStack Query
  • Global state: Zustand (lightweight) atau Context API untuk simple case
  • Jangan pakai Redux kecuali benar-benar perlu.

Styling

Gunakan Tailwind CSS atau shadcn/ui.

// Tailwind
<button className="rounded-lg bg-blue-600 px-4 py-2 text-white hover:bg-blue-700">
  Submit
</button>

Testing

# Unit test
pnpm vitest

# E2E
pnpm playwright test

Routing

App Router structure:

app/
├── (auth)/             # Route group
│   ├── login/
│   └── register/
├── dashboard/
│   ├── layout.tsx
│   └── page.tsx
├── api/
│   └── users/
│       └── route.ts    # API route
└── layout.tsx