React Router Code Review
Quick Reference
| Issue Type | Reference |
|---|---|
| useEffect for data, missing loaders, params | references/data-loading.md |
| Form vs useFetcher, action patterns | references/mutations.md |
| Missing error boundaries, errorElement | references/error-handling.md |
| navigate() vs Link, pending states | references/navigation.md |
Review Checklist
- • Data loaded via
loadernotuseEffect - • Route params accessed type-safely with validation
- • Using
defer()for parallel data fetching when appropriate - • Mutations use
<Form>oruseFetchernot manual fetch - • Actions handle both success and error cases
- • Error boundaries with
errorElementon routes - • Using
isRouteErrorResponse()to check error types - • Navigation uses
<Link>overnavigate()where possible - • Pending states shown via
useNavigation()orfetcher.state - • No navigation in render (only in effects or handlers)
Valid Patterns (Do NOT Flag)
These patterns are correct React Router usage - do not report as issues:
- •useEffect for client-only data - Loaders run server-side; localStorage, window dimensions, and browser APIs must use useEffect
- •navigate() in event handlers - Link is for declarative navigation; navigate() is correct for imperative navigation in callbacks/handlers
- •Type annotation on loader data -
useLoaderData<typeof loader>()is a type annotation, not a type assertion - •Empty errorElement at route level - Route may intentionally rely on parent error boundary
- •Form without action prop - Posts to current URL by convention; explicit action is optional
- •loader returning null - Valid when data may not exist; null is a legitimate loader return value
- •Using fetcher.data without checking fetcher.state - May be intentional when stale data is acceptable during revalidation
Context-Sensitive Rules
Only flag these issues when the specific context applies:
| Issue | Flag ONLY IF |
|---|---|
| Missing loader | Data is available server-side (not client-only) |
| useEffect for data fetching | Data is NOT client-only (localStorage, browser APIs, window size) |
| Missing errorElement | No parent route in the hierarchy has an error boundary |
| navigate() instead of Link | Navigation is NOT triggered by an event handler or conditional logic |
When to Load References
- •Reviewing data fetching code → data-loading.md
- •Reviewing forms or mutations → mutations.md
- •Reviewing error handling → error-handling.md
- •Reviewing navigation logic → navigation.md
Review Questions
- •Is data loaded in loaders instead of effects?
- •Are mutations using Form/action patterns?
- •Are there error boundaries at appropriate route levels?
- •Is navigation declarative with Link components?
- •Are pending states properly handled?
Before Submitting Findings
Load and follow review-verification-protocol before reporting any issue.