All skills
sergiodxa avatar

/frontend-react-router-best-practices

@9da9532

React Router performance and architecture patterns. Use when writing loaders, actions, forms, routes, or working with React Router data fetching. Triggers on tasks involving React Router routes, data loading, form handling, or route organization.

Use this Skill: https://skilld.dev/gh/sergiodxa/agent-skills/frontend-react-router-best-practices

This session only. Nothing lands on disk.

rulesdata-only-route-calls-hooks.md

≈583 tokens on demand. Your agent reads this file only when SKILL.md points to it.

Only Route Component Calls Data Hooks

Only the route's default export component should call useLoaderData and useActionData. Child components receive data via props.

Why

  • Clear data flow from route to children
  • Components are reusable and testable
  • Easier to understand where data comes from
  • Avoids hidden dependencies in child components

Pattern

// route.tsx
export async function loader({ request }: Route.LoaderArgs) {
  let client = await authenticate(request);
  let items = await getItems(client);
  return data({ items });
}

export async function action({ request }: Route.ActionArgs) {
  // ... handle action
  return data({ errors: [] });
}

// Only the route component calls the hooks
export default function Component() {
  const { items } = useLoaderData<typeof loader>();
  let actionData = useActionData<typeof action>();

  return (
    <div>
      {actionData?.errors && <ErrorList errors={actionData.errors} />}
      <ItemList items={items} />
    </div>
  );
}

Child Components Receive Props

// components/item-list.tsx
interface ItemListProps {
  items: Item[];
}

// Component receives data as props, doesn't call useLoaderData
export function ItemList({ items }: ItemListProps) {
  return (
    <ul>
      {items.map((item) => (
        <ItemCard key={item.id} item={item} />
      ))}
    </ul>
  );
}

// components/item-card.tsx
interface ItemCardProps {
  item: Item;
}

export function ItemCard({ item }: ItemCardProps) {
  return <li>{item.name}</li>;
}

Exception: Deeply Nested Data

For deeply nested components that need parent route data, use useRouteLoaderData:

// Deeply nested component needing user from parent layout
function UserAvatar() {
  // This is acceptable for layout-level data
  let data = useRouteLoaderData<typeof profileLoader>("routes/_._profile");
  return <Avatar src={data?.user.avatar} />;
}

Benefits

// Components are easily testable
import { render } from "@testing-library/react";
import { ItemList } from "./item-list";

test("renders items", () => {
  let items = [{ id: "1", name: "Test" }];
  render(<ItemList items={items} />);
  // No need to mock useLoaderData
});

Source: SKILL.md on GitHub

2 warnings16d5 checks · Risk SAFE
  • Gen Agent Trust Hub16d

    The skill provides a comprehensive set of developer guidelines and best practices for building React Router applications. It emphasizes performance, type safety, and security measures like input validation (Zod), safe redirects, and CSRF protection (Sec-Fetch). No malicious code, obfuscation, or data exfiltration patterns were detected.

  • Socket16d

    1 alert: gptSecurity

  • Snyk16d

    Risk: LOW · No issues

  • Runlayer7mo

    56/56 files flagged

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at 9da9532. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 months ago.

Dormantupdated 8 months ago

README badge

README badge for sergiodxa/agent-skills/frontend-react-router-best-practices