react-router
11
总安装量
2
周安装量
#28069
全站排名
安装命令
npx skills add https://github.com/iulspop/aidd-skills --skill react-router
Agent 安装分布
claude-code
2
Skill 文档
React Router
Act as a senior React Router engineer reviewing code for correctness, performance, and best practices.
Review: $ARGUMENTS
Loaders
- Fetch all data in loaders, never in components with
useEffect. Loaders run before render and eliminate loading spinners. - Use
Promise.allfor independent data fetches within a loader to avoid sequential waterfalls. - Use request-scoped caching (via context) so multiple loaders can call the same data function without duplicate requests.
- Control revalidation with
shouldRevalidateto skip unnecessary refetches. UseuseRevalidatorfor polling/focus patterns. - Type loaders with
Route.LoaderArgsand consume withuseLoaderData<typeof loader>(). - Validate URL params early with zod or invariant â don’t trust
paramsto be well-formed. - Pass
request.signalto fetch calls and database queries so they abort when the user navigates away. - Colocate data queries in
queries.server.tsnext to the route file.
Actions
- Validate all form data with zod schemas. Return validation errors with
data({ errors }, { status: 400 })â don’t throw for validation failures. - Use
throw redirect("/path")after successful mutations to prevent resubmission (Post/Redirect/Get). - Use zod
.transform()for input sanitization (trim, lowercase, parse numbers) during validation. - Use
z.discriminatedUnion("intent", [...])to handle multiple actions in one route with type-safe intent matching. - Use
clientActionfor instant client-side validation before hitting the server. - Re-throw redirects and unknown errors in catch blocks â only catch expected error types.
Forms
- Use
useFetcherfor in-place mutations (likes, toggles, inline edits) that shouldn’t trigger navigation. Use<Form>when the mutation should navigate. - Show pending state with
fetcher.state !== "idle"oruseNavigation().state. UseuseSpinDelayto avoid flicker. - Reset uncontrolled forms on success with
formRef.current?.reset()in an effect. - Return field values from actions on validation error so inputs repopulate with
defaultValue={actionData?.fields?.email}. - Add
<HoneypotInputs />to public-facing forms for bot protection.
Routing
- Organize routes as folders with colocated
queries.server.ts,actions.server.ts,route.tsx, andcomponents/. - Use resource routes (no default export) for API-like endpoints. Name them
api.<resource>.tsx. - Use dedicated action routes (
actions.<noun>-<verb>.ts) for reusable mutations consumed by multiple pages viauseFetcher. - Name the default export
Componentin all route files. - Never import from other route files â import shared modules instead. Exception: import
type { action }foruseFetchertype inference. - Access parent route data with
useRouteLoaderDatain UI. In loaders, re-fetch (request-scoped caching prevents duplicate calls).
Middleware
- Authenticate in middleware, authorize in each loader/action. Keep auth checks close to data access.
- Store session in middleware so loaders/actions get a single instance per request.
- Use
AsyncLocalStoragefor request-scoped context accessible without passing args through every function. - Add
Server-Timingheaders in middleware for performance observability. - Generate a request ID in middleware for log correlation across the request lifecycle.
Security
- Protect mutations with CSRF tokens or verify
Sec-Fetch-Siteheaders to reject cross-site requests. - Sanitize user-driven redirect URLs with
safeRedirect(redirectTo, "/")â never redirect to arbitrary user input. - Apply CORS headers only to API resource routes that need cross-origin access. Use specific origins, not wildcards.
- Validate cookie payloads with schemas using typed cookies.
- Use
prefetch="intent"on<Link>for faster navigation â preloads data on hover/focus.
Error Handling
- Export
ErrorBoundaryfrom every route with data fetching. UseisRouteErrorResponseto distinguish HTTP errors from unexpected exceptions. - In layout routes, make
ErrorBoundarylayout-aware so errors render within the app shell. - Use
<Suspense>with<Await resolve={promise}>for streamed loader data â return promises fromdata()and they auto-stream.