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.

rulesstreaming-await-suspense.md

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

Await with Suspense

Use Await component with Suspense fallback for streamed data.

Why

  • Await handles promise resolution from loader
  • Suspense provides loading UI while promise resolves
  • Enables streaming without blocking initial render
  • Error boundaries catch rejected promises

Basic Pattern

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

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

  return (
    <div>
      {/* Critical data renders immediately */}
      <h1>{criticalData.title}</h1>

      {/* Streamed data with loading state */}
      <Suspense fallback={<LoadingSkeleton />}>
        <Await resolve={streamedData}>
          {(data) => <DataDisplay data={data} />}
        </Await>
      </Suspense>
    </div>
  );
}

With Error Handling

<Suspense fallback={<Skeleton />}>
  <Await resolve={streamedData} errorElement={<ErrorMessage />}>
    {(data) => <DataDisplay data={data} />}
  </Await>
</Suspense>

Multiple Streamed Values

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

  return (
    <div>
      <ProfileHeader profile={profile} />

      {/* Each streamed value gets its own Suspense boundary */}
      <Suspense fallback={<ActivitySkeleton />}>
        <Await resolve={activities}>
          {(data) => <ActivityFeed activities={data} />}
        </Await>
      </Suspense>

      <Suspense fallback={<RecommendationSkeleton />}>
        <Await resolve={recommendations}>
          {(data) => <Recommendations items={data} />}
        </Await>
      </Suspense>
    </div>
  );
}

Nested Suspense for Prioritization

// Outer content loads first, inner content streams in
<Suspense fallback={<PageSkeleton />}>
  <Await resolve={mainContent}>
    {(content) => (
      <MainContent data={content}>
        {/* Nested streaming for secondary content */}
        <Suspense fallback={<SidebarSkeleton />}>
          <Await resolve={sidebarData}>
            {(sidebar) => <Sidebar data={sidebar} />}
          </Await>
        </Suspense>
      </MainContent>
    )}
  </Await>
</Suspense>

With Promise.all for Combined Data

When multiple promises should resolve together:

// Loader
return data({
  // Combine related promises
  widgetData: Promise.all([badges, privateStocks]),
});

// Component
<Suspense fallback={<WidgetSkeleton />}>
  <Await resolve={widgetData}>
    {([badges, privateStocks]) => (
      <Widgets badges={badges} stocks={privateStocks} />
    )}
  </Await>
</Suspense>;

Skeleton Components

Create skeleton components that match the final UI layout:

function ActivitySkeleton() {
  return (
    <div className="v-stack gap-4">
      {[1, 2, 3].map((i) => (
        <div key={i} className="h-stack gap-3 animate-pulse">
          <div className="w-10 h-10 bg-neutral-200 rounded-full" />
          <div className="v-stack gap-2 flex-1">
            <div className="h-4 bg-neutral-200 rounded w-3/4" />
            <div className="h-3 bg-neutral-200 rounded w-1/2" />
          </div>
        </div>
      ))}
    </div>
  );
}

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