Use Cases (Diperbarui: 3/6/2026)

Claude Code untuk Remix dan React Router: panduan loader/action

Bangun app bergaya Remix dengan Claude Code: loader, action, error boundary, SEO, dan prompt review.

Claude Code untuk Remix dan React Router: panduan loader/action

Cara melihat Remix pada 2026

Pada 2026, pengembangan Remix tidak hanya berarti merawat aplikasi Remix v2. Banyak ide Remix sekarang hidup di React Router v7 Framework Mode, dan dokumentasi resmi Remix mengarahkan pembaca ke React Router untuk fitur framework terbaru. Ini penting saat memakai Claude Code. Jika prompt hanya berbunyi “buat dengan Remix”, hasilnya bisa mencampur import lama dari@remix-run/*, import baru darireact-router, dan alurfetch client-side yang seharusnya tidak perlu.

Penjelasan paling mudah untuk pemula adalah: gaya Remix/React Router menaruhloader danaction di level route, sehingga logika server dan UI berdekatan. loader membaca data sebelum halaman dirender. action menangani submit form dan perubahan data. Komponen merender UI, sementara route yang sama bisa memilikiErrorBoundary dan metadata SEO. Dengan bentuk seperti ini, Claude Code bisa diminta mengecek satu route secara utuh: baca data, tulis data, state user, error, dan snippet pencarian.

Artikel ini memakai React Router v7 Framework Mode dan membuat mini app yang bisa disalin: daftar produk, detail produk, dan form kontak. Tiga use case utama adalah mengambil data denganloader, memproses form denganaction, dan membatasi kegagalan denganErrorBoundary. Artikel juga menyertakan prompt review, kesalahan umum, internal link, dan jalur monetisasi. Referensi resmi yang diperiksa adalah Remix Docs, React Router v7, Route Module docs, Error Boundaries docs, dan Form API.

flowchart LR
  A["URL / route"] --> B["loader membaca data"]
  B --> C["UI component"]
  C --> D["Form submit"]
  D --> E["action validasi dan tulis"]
  E --> B
  B --> F["ErrorBoundary"]
  E --> F

Tentukan mode lebih dulu

React Router v7 bisa dipakai dalam Declarative, Data, atau Framework Mode. Pengalaman yang paling dekat dengan Remix adalah Framework Mode: route modules, server rendering,loader, action, type generation, dan konvensi deployment ada dalam satu bentuk proyek.

SituasiPilihanInstruksi untuk Claude Code
App bisnis baruReact Router v7 Framework ModePakaicreate-react-router dan route modules
Remix v2 yang sudah adaIkuti pola lamaSesuaikan dengan import@remix-run/* di repo
React SPA lamaMigrasi bertahapPindahkan satu layar ke loader/action
Landing page dengan formFramework atau SPA ModePutuskan SSR dan server action sejak awal

Keputusan ini mengurangi revisi. Claude Code cepat, tetapi tanpa batas yang jelas ia akan menggabungkan contoh dari beberapa versi. Di sini kita memakai React Router v7 Framework Mode.

Mini project yang bisa dijalankan

Mulai dari kecil. Daftar produk, detail, dan kontak sudah cukup untuk menguji data, mutation, error, dan SEO.

npx create-react-router@latest rr-claude-shop
cd rr-claude-shop
npm install
npm run dev
// app/routes.ts
import { type RouteConfig, index, route } from "@react-router/dev/routes";

export default [
  index("routes/home.tsx"),
  route("products", "routes/products.tsx"),
  route("products/:productId", "routes/products.$productId.tsx"),
  route("contact", "routes/contact.tsx"),
] satisfies RouteConfig;

Data pertama disimpan di modul server-only. Nanti modul ini bisa diganti Prisma, Drizzle, Supabase, atau API internal tanpa membuat route terlalu rumit.

// app/data/products.server.ts
export type Product = {
  id: string;
  name: string;
  description: string;
  price: number;
};

const products: Product[] = [
  {
    id: "starter",
    name: "Claude Code Starter Kit",
    description: "Small prompts and review checklists for the first team rollout.",
    price: 9800,
  },
  {
    id: "team",
    name: "Team Workflow Pack",
    description: "Route reviews, test prompts, and deployment checklists for teams.",
    price: 29800,
  },
];

const leads: Array<{ id: string; email: string; message: string }> = [];

export async function listProducts(query = "") {
  const q = query.trim().toLowerCase();
  if (!q) return products;
  return products.filter((product) =>
    `${product.name} ${product.description}`.toLowerCase().includes(q),
  );
}

export async function getProduct(productId: string) {
  return products.find((product) => product.id === productId) ?? null;
}

export async function saveLead(input: { email: string; message: string }) {
  const lead = { id: crypto.randomUUID(), ...input };
  leads.push(lead);
  return lead;
}

Use case 1: membaca data dengan loader

loader mengumpulkan data sebelum route dirender. Ini lebih mudah direview daripada mengambil data awal melaluiuseEffect, karena loading, error, dan SEO berada dekat dengan route.

// app/routes/products.tsx
import { Form, Link, useLoaderData, useNavigation } from "react-router";
import { listProducts } from "~/data/products.server";

export async function loader({ request }: { request: Request }) {
  const url = new URL(request.url);
  const q = url.searchParams.get("q") ?? "";
  const products = await listProducts(q);
  return { q, products };
}

export default function ProductsRoute() {
  const { q, products } = useLoaderData<typeof loader>();
  const navigation = useNavigation();
  const searching = navigation.location?.pathname === "/products";

  return (
    <main>
      <title>Products | Claude Code Shop</title>
      <meta
        name="description"
        content="Browse Claude Code workflow products and team enablement kits."
      />
      <h1>Products</h1>
      <Form method="get" role="search">
        <label>
          Search
          <input name="q" defaultValue={q} placeholder="workflow" />
        </label>
        <button type="submit">{searching ? "Searching..." : "Search"}</button>
      </Form>
      <ul>
        {products.map((product) => (
          <li key={product.id}>
            <Link to={`/products/${product.id}`}>{product.name}</Link>
            <p>{product.description}</p>
            <strong>{product.price.toLocaleString()} JPY</strong>
          </li>
        ))}
      </ul>
    </main>
  );
}

Untuk kode baru dengan React 19, dokumentasi route module menyarankan elemen bawaan<title> dan<meta>. Jika aplikasi lama memakai exportmeta(), pertahankan konsistensinya. Yang penting, setiap route punya title dan description yang unik.

Use case 2: memproses form dengan action

action menerima submit form dan mutation. <Form> tetap bekerja sebagai HTML form biasa sebelum JavaScript aktif, lalu React Router menambahkan state submit dan revalidation.

// app/routes/contact.tsx
import { Form, useActionData, useNavigation } from "react-router";
import { saveLead } from "~/data/products.server";

type ActionData =
  | { ok: true; leadId: string }
  | { ok: false; errors: { email?: string; message?: string } };

export async function action({ request }: { request: Request }): Promise<ActionData> {
  const formData = await request.formData();
  const email = String(formData.get("email") ?? "").trim();
  const message = String(formData.get("message") ?? "").trim();
  const errors: { email?: string; message?: string } = {};

  if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
    errors.email = "Enter a valid email address.";
  }
  if (message.length < 20) {
    errors.message = "Tell us at least 20 characters about your situation.";
  }
  if (Object.keys(errors).length > 0) {
    return { ok: false, errors };
  }

  const lead = await saveLead({ email, message });
  return { ok: true, leadId: lead.id };
}

Dalam aplikasi nyata, tambahkan CSRF, rate limit, anti-spam, email, dan integrasi CRM. Prompt yang baik bukan “buat form”, tetapi “pakai action, validasi di server, tampilkan error per field, disable tombol saat submit, dan tampilkan sukses”.

Use case 3: membatasi error dengan ErrorBoundary

Jika produk tidak ditemukan, route detail cukup menampilkan 404 lokal. Seluruh app tidak perlu crash.

// app/routes/products.$productId.tsx
import { data, isRouteErrorResponse, Link, useLoaderData } from "react-router";
import { getProduct } from "~/data/products.server";

export async function loader({ params }: { params: { productId?: string } }) {
  const productId = params.productId;
  if (!productId) {
    throw data("Missing product id", { status: 400 });
  }
  const product = await getProduct(productId);
  if (!product) {
    throw data("Product not found", { status: 404 });
  }
  return { product };
}

export function ErrorBoundary({ error }: { error: unknown }) {
  if (isRouteErrorResponse(error)) {
    return (
      <main>
        <h1>{error.status === 404 ? "Product not found" : "Could not load product"}</h1>
        <p>{error.data}</p>
        <Link to="/products">Back to products</Link>
      </main>
    );
  }
  return <main><h1>Unexpected error</h1><p>Please try again later.</p></main>;
}

Saat review, pastikan error yang wajar memberi langkah berikutnya, sedangkan error tak terduga tidak membocorkanerror.stack, secret, pesan database, atau URL internal.

SEO sebaiknya menjadi bagian dari desain route. Halaman daftar menjelaskan apa yang bisa dibandingkan, halaman detail memulai dari nama produk, dan halaman kontak menjelaskan bantuan apa yang tersedia. Internal link seperti Claude Code React development, Claude Code API development, dan error handling patterns membuat pembaca masuk lebih dalam.

Review route module React Router v7 Framework Mode ini.
Cek loader, action, ErrorBoundary, Form, title/description, dan imports.
Urutkan masalah berdasarkan severity, usulkan diff paling kecil, lalu tulis command verifikasi.

Kesalahan umum: mencampur import lama dan baru, mengembalikan data privat dariloader, percaya hanya pada validasi browser, menampilkan stack trace, menggandakan SEO title, dan tidak memahami revalidation setelahaction. Untuk latihan pribadi, mulai dari free cheat sheet. Untuk tim yang perlu React Router v7, maintenance Remix v2, desain form, dan review workflow Claude Code, lihat training dan konsultasi Claude Code. Prompt dan checklist reusable ada di produk.

Masa menguji pencarian produk, 404 detail, validasi form kontak, dan pesan sukses di project kecil. Prompt samar “buat dengan Remix” menghasilkan import campur dan clientfetch. Ketika prompt menyebut Framework Mode, route modules,loader, action, ErrorBoundary, dantitle/meta, diff menjadi lebih kecil dan mudah direview. Jadi, tetapkan dulu tanggung jawab route, baru biarkan Claude Code mempercepat implementasi.

#Claude Code #Remix #React #full-stack #frontend
Gratis

PDF gratis: cheatsheet Claude Code

Masukkan email dan unduh satu halaman berisi command, kebiasaan review, dan workflow aman.

Kami menjaga datamu dan tidak mengirim spam.

Masa

Tentang penulis

Masa

Engineer yang berfokus pada workflow Claude Code praktis dan adopsi tim.