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.

rulesmigrate-defer-to-data.md

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

Single Fetch Migration

Migrate from defer() to data() pattern for Single Fetch. Promises automatically stream.

Why

  • Single Fetch is enabled (v3_singleFetch: true in remix.config)
  • data() is the new standard, defer() is deprecated
  • Promises in data() response automatically stream
  • Cleaner API, no special handling needed

Migration Pattern

Before (defer)

import { defer } from "react-router";

export async function loader({ request }: Route.LoaderArgs) {
  let criticalData = await getCriticalData();

  return defer({
    critical: criticalData,
    lazy: getLazyData(), // Promise - must use defer for streaming
  });
}

After (data with Single Fetch)

import { data } from "react-router";

export async function loader({ request }: Route.LoaderArgs) {
  let criticalData = await getCriticalData();

  return data({
    critical: criticalData,
    lazy: getLazyData(), // Promise - automatically streams with Single Fetch
  });
}

Example: Mixing Awaited and Streamed Data

import { data } from "react-router";

export async function loader({ request, context }: Route.LoaderArgs) {
  let client = await authenticate(request);

  // Critical data - await before returning
  const [profile, settings] = await Promise.all([
    queryProfile(client),
    querySettings(client),
  ]);

  return data({
    profile,
    settings,
    // Non-critical data - streams automatically
    activities: queryActivities(client),
    notifications: queryNotifications(client),
    recommendations: queryRecommendations(client),
  });
}

Component Usage

The component usage with <Await> and <Suspense> stays the same:

import { Await, useLoaderData } from "react-router";
import { Suspense } from "react";

export default function Component() {
  const { profile, activities } = useLoaderData<typeof loader>();

  return (
    <div>
      {/* Critical data renders immediately */}
      <h1>{profile.name}</h1>

      {/* Streamed data with Suspense */}
      <Suspense fallback={<ActivitySkeleton />}>
        <Await resolve={activities}>
          {(data) => <ActivityFeed activities={data} />}
        </Await>
      </Suspense>
    </div>
  );
}

When to Await vs Stream

return data({
  // AWAIT: Critical for initial render, SEO, or needed by other data
  user: await getUser(request), // Await - needed for auth
  title: await getPageTitle(), // Await - needed for SEO

  // STREAM: Non-critical, below fold, or slow queries
  comments: getComments(postId), // Stream - below fold
  recommendations: getRecommendations(), // Stream - non-critical
  analytics: getAnalytics(), // Stream - slow query
});

Non-Streaming (All Data Awaited)

When all data is critical and needs to be sent at once:

import { data } from "react-router";

export async function loader({ request }: Route.LoaderArgs) {
  const [a, b, c] = await Promise.all([getA(), getB(), getC()]);
  return data({ a, b, c }); // All data sent at once, no streaming
}

Note: Always use data() - json() is deprecated with Single Fetch.

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