Way TypeScript & React Style
Way Specific Conventions
- Define reusable data/logic helpers as top-level pure functions (outside React components); keep component bodies focused on rendering and wiring
- Complex predicates for array methods must be separate named functions
- Prefer declarative over imperative — derive values during render rather than storing them in
let/useState; use map/filter/reduce expressions rather than loops that push into an array; use object/array spread to produce new values rather than mutating existing ones
- Always use early returns —
if (isLoading) return <Spinner />; at the top, not let content with if/else branches
- Never use IIFEs — extract a named function instead: a top-level pure function for derived values, or a named inner function for JSX that closes over component state
- Avoid
as casts; prefer narrowing, generics, or splitting code paths. Use as only when interoperating with external/untyped APIs and add a short justification comment
- Handle undefined args explicitly (no
?? 0 for mandatory params)
- Naming: names describe the entity, not the mechanism. No suffixes like
Base/New/Old/Initial unless they carry real semantic meaning. Keep sibling verbs consistent across a related API. Avoid cryptic identifiers (v, n) for domain values — short names are fine only in conventional contexts (i, x/y, generic T/K/V)
- Code structure: prioritize reusing
lib/hooks/components over duplicating logic; promote generic helpers out of feature folders into lib/ or hooks/. Keep functions small and single-purpose — split 100+ line functions into focused named helpers. Extract distinct complex JSX into named components when it helps reuse, coupling, or readability
- Comments: none by default — well-named identifiers carry the
what. Add a short comment only when the why is non-obvious (a workaround, a hidden invariant, a subtle ordering constraint); never document the implementation itself
- Do NOT use
useMemo or useCallback — React Compiler handles memoization. (Project AGENTS.md may define narrow exceptions.)
- STOP before writing
useEffect — most uses are wrong. Evaluate the decision tree in this skill first. Effects are only for synchronizing with external systems.
- Data fetching hierarchy: Always use
@connectrpc/connect-query hooks with generated *_connectquery.ts files. Only fall back to raw @tanstack/react-query when no generated file exists or the pattern cannot be expressed via connect-query.
- Hydration: Never render server-side content that depends on client state (timestamps,
window checks)
STOP — Before Writing useEffect
Effects are an escape hatch for synchronizing with external systems — if no external system is involved, you almost certainly don't need one.
Decision tree
About to write useEffect?
│
├─ Responding to a user action (click, submit, drag)?
│ └─ Use an EVENT HANDLER — you know exactly what happened
│
├─ Deriving a value from props or state?
│ └─ COMPUTE DURING RENDER — const fullName = first + ' ' + last
│
├─ Need to reset state when a prop changes?
│ └─ Use the KEY PROP — <Profile key={userId} />
│
├─ Filtering/transforming data?
│ └─ COMPUTE DURING RENDER (useMemo if expensive)
│
├─ Notifying a parent of a state change?
│ └─ Call the callback IN THE SAME EVENT HANDLER
│
├─ Chaining multiple state updates?
│ └─ Calculate ALL next state IN THE EVENT HANDLER
│
└─ Synchronizing with a non-React system (DOM API, WebSocket, browser API)?
└─ This is the ONE case where useEffect is correct
└─ Always include cleanup. For subscriptions, prefer useSyncExternalStore.
The top anti-patterns
| Anti-pattern |
What to do instead |
useState + useEffect to derive a value |
Compute during render: const x = a + b |
useEffect to filter/transform data |
Compute during render (or useMemo) |
useEffect to reset state on prop change |
key prop on the component |
useEffect to respond to a click/submit |
Put the logic in the event handler |
useEffect calling parent's onChange |
Call onChange in the event handler |
| Chain of Effects triggering each other |
Compute all state changes in one event handler |
useEffect fetching without cleanup |
Add let ignore = false cleanup (or use useQuery) |
App init in useEffect([], ...) |
Module-level let didInit = false guard |
For detailed examples with incorrect/correct code, see:
- useEffect Anti-Patterns — 9 common mistakes with fixes
- Better Alternatives —
useMemo, key prop, lifting state, useSyncExternalStore, event handlers
STOP — Before Writing Data Fetching Hooks
The most common mistake is reaching for raw @tanstack/react-query hooks when generated @connectrpc/connect-query hooks should be used instead. This causes redundant boilerplate, breaks transport injection, and bypasses the project's auth/error-handling layer.
The hierarchy (follow in order)
Fetching data from a ConnectRPC service?
│
├─ Is there a generated *_connectquery.ts file for this method?
│ └─ YES → Use @connectrpc/connect-query hooks ← DEFAULT
│ import { useQuery, useMutation } from "@connectrpc/connect-query"
│ import { listThings } from "@/gen/proto/.../*_connectquery"
│ const { data } = useQuery(listThings, { orgPath }, { transport })
│
└─ NO generated file, or need a pattern connect-query can't express?
└─ Fall back to @tanstack/react-query directly
import { useQuery } from "@tanstack/react-query"
(custom queryFn, useInfiniteQuery with complex pagination, etc.)
connect-query patterns
// READ — useQuery
import { useQuery } from "@connectrpc/connect-query";
import { listThings } from "@/gen/proto/.../things_service-ThingsService_connectquery";
const transport = useClientConfig();
const { data, isLoading } = useQuery(listThings, { orgPath }, { transport });
// Conditional skip — use skipToken (NOT enabled: false)
import { skipToken } from "@tanstack/react-query";
const { data } = useQuery(listThings, orgPath ? { orgPath } : skipToken, { transport });
// WRITE — useMutation
import { useMutation } from "@connectrpc/connect-query";
const { mutate, isPending } = useMutation(deleteThing, {
transport,
onError: (error) => toastApiError(error, t("deleteFailed")),
});
// Cache invalidation after mutation
import { createConnectQueryKey } from "@connectrpc/connect-query";
const queryClient = useQueryClient();
queryClient.invalidateQueries({
queryKey: createConnectQueryKey({ schema: listThings, transport, cardinality: "finite" }),
});
When raw tanstack-query IS appropriate
- Non-RPC fetches (REST endpoints, third-party APIs)
- Complex multi-RPC
queryFn that composes several calls imperatively
useSuspenseQuery / useSuspenseInfiniteQuery if not yet supported by connect-query
- When you need
queryOptions() helper for SSR prefetching patterns
For the full tanstack-query API reference see references/tanstack-query.md.
TypeScript Style
Types
- Never use boxed types (
Number, String, Boolean, Symbol, Object). Use the lowercase primitives (number, string, boolean, symbol, object).
- Never use
any unless migrating from JavaScript. Use unknown for truly unknown values.
- Never have unused type parameters in generics.
Callbacks
- Return
void, not any, for callbacks whose return value is ignored. void prevents accidental use of the return value.
- Don't make callback parameters optional — callers can always pass a function that accepts fewer arguments.
- Don't overload on callback arity — write a single overload with the maximum arity.
Type Safety in Practice
See TypeScript Do's and Don'ts for the full guide on types, casting, and any/unknown.
- Narrow, don't cast — use type guards, discriminated unions, and
satisfies instead of as.
- Prefer
unknown over any — force explicit narrowing at the call site.
- Use
satisfies to validate a value matches a type without widening it: const config = { ... } satisfies Config.
- Prefer
readonly for data that shouldn't be mutated (function parameters, returned arrays).
- Avoid enums in application code — use
as const objects or string literal unions. (Generated proto enums are the exception.)
React Rules
These are rules, not guidelines — breaking them causes bugs. Condensed from the official Rules of React.
1. Components & Hooks Must Be Pure
- Idempotent: Same inputs (props, state, context) must produce the same output. Don't use
new Date() or Math.random() during render — move them to effects or event handlers.
- No side effects in render: React can render components multiple times. Side effects belong in event handlers or
useEffect.
- Local mutation is fine: Creating and modifying local variables during render is OK — the mutation isn't remembered between renders.
- Props, state, and hook return values are immutable: Never mutate them directly. Use setter functions.
- Don't mutate values after passing to JSX: React may evaluate JSX eagerly; mutating after the fact leads to stale UI.
2. React Controls Invocation
- Never call component functions directly — use them in JSX. React needs to orchestrate rendering, reconciliation, and state management.
- Never pass hooks around as values — always call hooks inline. Don't dynamically mutate or inject hooks.
3. Rules of Hooks
- Top level only — no hooks in loops, conditions, nested functions, try/catch, or after early returns.
- React functions only — call hooks from function components or custom hooks, never from regular functions.
React & Next.js Performance
See references/vercel-rules/ for the full 57-rule reference. Key patterns:
Eliminating Waterfalls
- Move
await into the branch that uses it — don't block early returns with unneeded fetches
Promise.all() for independent operations; start promises early, await late
- Wrap slow data components in
<Suspense> so the surrounding layout renders immediately
- Sibling async Server Components fetch in parallel; a parent that
awaits before rendering children creates a waterfall
Bundle Size
- Import directly from source files, not barrel
index.ts re-exports
next/dynamic for heavy components (maps, editors, charts)
- Defer analytics/logging with
dynamic(() => ..., { ssr: false })
- Trigger
import() on hover/focus to preload before click
Server-Side Performance
- Verify auth inside every Server Action — don't rely on middleware alone
- Pass only the fields a client component actually uses (no 50-field objects)
- Sibling async Server Components fetch in parallel; awaiting in a parent creates a waterfall
React.cache() deduplicates calls within one request (avoid inline object args)
after() for logging/analytics so it doesn't block the response
Re-render Optimization
- Derive values during render — don't store computed state or sync via effects
setState(prev => ...) when new state depends on previous value
useState(() => expensiveInit()) — function form, not expression
- Depend on
user.id not user; derive booleans and depend on those
useRef for transient values (mouse position, timers, flags)
startTransition for non-urgent updates
Rendering Performance
- Explicit conditional rendering: Use ternary (
condition ? <A /> : null), not &&, when the condition could be 0 or NaN.
- Animate SVG wrappers: Wrap SVG in a
<div> and animate the wrapper for GPU acceleration.
content-visibility: auto: Defer off-screen rendering for long lists.
- Hydration mismatches: Use
suppressHydrationWarning only for expected differences (timestamps, locales). For client-only data (theme), use an inline <script> to set the DOM before hydration.
JavaScript Performance
Set/Map for repeated lookups instead of array scans
toSorted() / toReversed() / toSpliced() — .sort() mutates
- Combine multiple
.filter()/.map() passes into one loop
- Hoist
RegExp to module scope; cache localStorage reads in a module-level Map
Advanced Patterns
- Initialize once per app load: Don't put one-time init in
useEffect([], ...) — it re-runs on remount and runs twice in dev. Use a module-level let didInit = false guard.
useEffectEvent: Creates a stable function reference that always calls the latest handler, without adding the handler to effect dependencies.
Testing Best Practise
STOP before writing or reviewing vitest tests — load references/testing-best-practices.md first. It covers the NEVER-do list (untestable files, mock cleanup, loose assertions, testing implementation details, skipping tsc --noEmit on test files, and more), the questions to ask before writing a test, the pre-write and test-review workflows, and links to 12 detailed pattern files in references/testing/ plus the review report template in assets/testing-output-report-template.md.
Available References
Detailed documentation available in the references/ directory:
- useEffect Anti-Patterns: 9 common mistakes with incorrect/correct code examples.
- useEffect Alternatives:
useMemo, key prop, lifting state, useSyncExternalStore, event handlers, custom hooks.
- TypeScript Do's and Don'ts: Official TypeScript handbook guidance on types, callbacks, and overloads, plus casting/
any/unknown guidance.
- Rules of React: All four pages of React's official rules — purity, invocation, hooks.
- Vercel React Rules: 57 individual rule files with incorrect/correct code examples. Named by category prefix:
async-*, bundle-*, server-*, client-*, rerender-*, rendering-*, js-*, advanced-*. Load individual files on demand rather than the full set.
- TanStack Query Reference: Full API reference for
@tanstack/react-query v5 — for fallback cases where connect-query is insufficient.
- Testing Best Practices: Full vitest testing guide — NEVER-do list, pre-write checklist, workflows for writing and reviewing tests, and a table of detailed pattern files.
- Vitest Pattern Files: 12 files covering organization, AAA pattern, parameterized tests, error handling, assertions, test doubles, async testing, performance, vitest features, snapshot testing, property-based testing, and a quick-start example. Load individual files on demand, per the table in testing-best-practices.md.
- Test Review Report Template: Standardized format for test code review/audit findings — severity levels, impact analysis, and a summary table.
1---2name: way-typescript-react-style3description: Guide for writing idiomatic, high-quality TypeScript and React code, and for writing or reviewing vitest tests. Use this skill when writing, refactoring, or reviewing TypeScript/React code or test files to ensure adherence to established conventions, React rules, performance best practices, and vitest testing patterns. Trigger proactively when writing React components, TypeScript types, Next.js pages, or vitest tests, or when auditing existing tests.4---56# Way TypeScript & React Style78## Way Specific Conventions910- Define reusable data/logic helpers as top-level pure functions (outside React components); keep component bodies focused on rendering and wiring11- Complex predicates for array methods must be separate named functions12- **Prefer declarative over imperative** — derive values during render rather than storing them in `let`/`useState`; use `map`/`filter`/`reduce` expressions rather than loops that push into an array; use object/array spread to produce new values rather than mutating existing ones13- **Always use early returns** — `if (isLoading) return <Spinner />;` at the top, not `let content` with if/else branches14- **Never use IIFEs** — extract a named function instead: a top-level pure function for derived values, or a named inner function for JSX that closes over component state15- Avoid `as` casts; prefer narrowing, generics, or splitting code paths. Use `as` only when interoperating with external/untyped APIs and add a short justification comment16- Handle undefined args explicitly (no `?? 0` for mandatory params)17- **Naming**: names describe the entity, not the mechanism. No suffixes like `Base`/`New`/`Old`/`Initial` unless they carry real semantic meaning. Keep sibling verbs consistent across a related API. Avoid cryptic identifiers (`v`, `n`) for domain values — short names are fine only in conventional contexts (`i`, `x`/`y`, generic `T`/`K`/`V`)18- **Code structure**: prioritize reusing `lib`/`hooks`/`components` over duplicating logic; promote generic helpers out of feature folders into `lib/` or `hooks/`. Keep functions small and single-purpose — split 100+ line functions into focused named helpers. Extract distinct complex JSX into named components when it helps reuse, coupling, or readability19- **Comments**: none by default — well-named identifiers carry the `what`. Add a short comment only when the `why` is non-obvious (a workaround, a hidden invariant, a subtle ordering constraint); never document the implementation itself20- **Do NOT use `useMemo` or `useCallback`** — React Compiler handles memoization. (Project AGENTS.md may define narrow exceptions.)21- **STOP before writing `useEffect`** — most uses are wrong. Evaluate the decision tree in this skill first. Effects are only for synchronizing with external systems.22- **Data fetching hierarchy**: Always use `@connectrpc/connect-query` hooks with generated `*_connectquery.ts` files. Only fall back to raw `@tanstack/react-query` when no generated file exists or the pattern cannot be expressed via connect-query.23- **Hydration**: Never render server-side content that depends on client state (timestamps, `window` checks)2425---2627## STOP — Before Writing `useEffect`2829Effects are an **escape hatch** for synchronizing with external systems — if no external system is involved, you almost certainly don't need one.3031### Decision tree3233```34About to write useEffect?35│36├─ Responding to a user action (click, submit, drag)?37│ └─ Use an EVENT HANDLER — you know exactly what happened38│39├─ Deriving a value from props or state?40│ └─ COMPUTE DURING RENDER — const fullName = first + ' ' + last41│42├─ Need to reset state when a prop changes?43│ └─ Use the KEY PROP — <Profile key={userId} />44│45├─ Filtering/transforming data?46│ └─ COMPUTE DURING RENDER (useMemo if expensive)47│48├─ Notifying a parent of a state change?49│ └─ Call the callback IN THE SAME EVENT HANDLER50│51├─ Chaining multiple state updates?52│ └─ Calculate ALL next state IN THE EVENT HANDLER53│54└─ Synchronizing with a non-React system (DOM API, WebSocket, browser API)?55 └─ This is the ONE case where useEffect is correct56 └─ Always include cleanup. For subscriptions, prefer useSyncExternalStore.57```5859### The top anti-patterns6061| Anti-pattern | What to do instead |62|---|---|63| `useState` + `useEffect` to derive a value | Compute during render: `const x = a + b` |64| `useEffect` to filter/transform data | Compute during render (or `useMemo`) |65| `useEffect` to reset state on prop change | `key` prop on the component |66| `useEffect` to respond to a click/submit | Put the logic in the event handler |67| `useEffect` calling parent's `onChange` | Call `onChange` in the event handler |68| Chain of Effects triggering each other | Compute all state changes in one event handler |69| `useEffect` fetching without cleanup | Add `let ignore = false` cleanup (or use `useQuery`) |70| App init in `useEffect([], ...)` | Module-level `let didInit = false` guard |7172For detailed examples with incorrect/correct code, see:73- **[useEffect Anti-Patterns](references/useeffect-anti-patterns.md)** — 9 common mistakes with fixes74- **[Better Alternatives](references/useeffect-alternatives.md)** — `useMemo`, `key` prop, lifting state, `useSyncExternalStore`, event handlers7576---7778## STOP — Before Writing Data Fetching Hooks7980**The most common mistake is reaching for raw `@tanstack/react-query` hooks when generated `@connectrpc/connect-query` hooks should be used instead.** This causes redundant boilerplate, breaks transport injection, and bypasses the project's auth/error-handling layer.8182### The hierarchy (follow in order)8384```85Fetching data from a ConnectRPC service?86│87├─ Is there a generated *_connectquery.ts file for this method?88│ └─ YES → Use @connectrpc/connect-query hooks ← DEFAULT89│ import { useQuery, useMutation } from "@connectrpc/connect-query"90│ import { listThings } from "@/gen/proto/.../*_connectquery"91│ const { data } = useQuery(listThings, { orgPath }, { transport })92│93└─ NO generated file, or need a pattern connect-query can't express?94 └─ Fall back to @tanstack/react-query directly95 import { useQuery } from "@tanstack/react-query"96 (custom queryFn, useInfiniteQuery with complex pagination, etc.)97```9899### connect-query patterns100101```ts102// READ — useQuery103import { useQuery } from "@connectrpc/connect-query";104import { listThings } from "@/gen/proto/.../things_service-ThingsService_connectquery";105const transport = useClientConfig();106const { data, isLoading } = useQuery(listThings, { orgPath }, { transport });107108// Conditional skip — use skipToken (NOT enabled: false)109import { skipToken } from "@tanstack/react-query";110const { data } = useQuery(listThings, orgPath ? { orgPath } : skipToken, { transport });111112// WRITE — useMutation113import { useMutation } from "@connectrpc/connect-query";114const { mutate, isPending } = useMutation(deleteThing, {115 transport,116 onError: (error) => toastApiError(error, t("deleteFailed")),117});118119// Cache invalidation after mutation120import { createConnectQueryKey } from "@connectrpc/connect-query";121const queryClient = useQueryClient();122queryClient.invalidateQueries({123 queryKey: createConnectQueryKey({ schema: listThings, transport, cardinality: "finite" }),124});125126```127128### When raw tanstack-query IS appropriate129130- Non-RPC fetches (REST endpoints, third-party APIs)131- Complex multi-RPC `queryFn` that composes several calls imperatively132- `useSuspenseQuery` / `useSuspenseInfiniteQuery` if not yet supported by connect-query133- When you need `queryOptions()` helper for SSR prefetching patterns134135For the full tanstack-query API reference see [references/tanstack-query.md](references/tanstack-query.md).136137---138139## TypeScript Style140141### Types142143- **Never use boxed types** (`Number`, `String`, `Boolean`, `Symbol`, `Object`). Use the lowercase primitives (`number`, `string`, `boolean`, `symbol`, `object`).144- **Never use `any`** unless migrating from JavaScript. Use `unknown` for truly unknown values.145- **Never have unused type parameters** in generics.146147### Callbacks148149- **Return `void`**, not `any`, for callbacks whose return value is ignored. `void` prevents accidental use of the return value.150- **Don't make callback parameters optional** — callers can always pass a function that accepts fewer arguments.151- **Don't overload on callback arity** — write a single overload with the maximum arity.152153### Type Safety in Practice154155See [TypeScript Do's and Don'ts](references/typescript-dos-and-donts.md) for the full guide on types, casting, and `any`/`unknown`.156157- **Narrow, don't cast** — use type guards, discriminated unions, and `satisfies` instead of `as`.158- **Prefer `unknown` over `any`** — force explicit narrowing at the call site.159- **Use `satisfies`** to validate a value matches a type without widening it: `const config = { ... } satisfies Config`.160- **Prefer `readonly`** for data that shouldn't be mutated (function parameters, returned arrays).161- **Avoid enums** in application code — use `as const` objects or string literal unions. (Generated proto enums are the exception.)162163## React Rules164165These are rules, not guidelines — breaking them causes bugs. Condensed from the [official Rules of React](references/react-rules.md).166167### 1. Components & Hooks Must Be Pure168169- **Idempotent**: Same inputs (props, state, context) must produce the same output. Don't use `new Date()` or `Math.random()` during render — move them to effects or event handlers.170- **No side effects in render**: React can render components multiple times. Side effects belong in event handlers or `useEffect`.171- **Local mutation is fine**: Creating and modifying local variables during render is OK — the mutation isn't remembered between renders.172- **Props, state, and hook return values are immutable**: Never mutate them directly. Use setter functions.173- **Don't mutate values after passing to JSX**: React may evaluate JSX eagerly; mutating after the fact leads to stale UI.174175### 2. React Controls Invocation176177- **Never call component functions directly** — use them in JSX. React needs to orchestrate rendering, reconciliation, and state management.178- **Never pass hooks around as values** — always call hooks inline. Don't dynamically mutate or inject hooks.179180### 3. Rules of Hooks181182- **Top level only** — no hooks in loops, conditions, nested functions, try/catch, or after early returns.183- **React functions only** — call hooks from function components or custom hooks, never from regular functions.184185## React & Next.js Performance186187See `references/vercel-rules/` for the full 57-rule reference. Key patterns:188189### Eliminating Waterfalls190191- Move `await` into the branch that uses it — don't block early returns with unneeded fetches192- `Promise.all()` for independent operations; start promises early, await late193- Wrap slow data components in `<Suspense>` so the surrounding layout renders immediately194- Sibling async Server Components fetch in parallel; a parent that `await`s before rendering children creates a waterfall195196### Bundle Size197198- Import directly from source files, not barrel `index.ts` re-exports199- `next/dynamic` for heavy components (maps, editors, charts)200- Defer analytics/logging with `dynamic(() => ..., { ssr: false })`201- Trigger `import()` on hover/focus to preload before click202203### Server-Side Performance204205- Verify auth inside every Server Action — don't rely on middleware alone206- Pass only the fields a client component actually uses (no 50-field objects)207- Sibling async Server Components fetch in parallel; awaiting in a parent creates a waterfall208- `React.cache()` deduplicates calls within one request (avoid inline object args)209- `after()` for logging/analytics so it doesn't block the response210211### Re-render Optimization212213- Derive values during render — don't store computed state or sync via effects214- `setState(prev => ...)` when new state depends on previous value215- `useState(() => expensiveInit())` — function form, not expression216- Depend on `user.id` not `user`; derive booleans and depend on those217- `useRef` for transient values (mouse position, timers, flags)218- `startTransition` for non-urgent updates219220### Rendering Performance221222- **Explicit conditional rendering**: Use ternary (`condition ? <A /> : null`), not `&&`, when the condition could be `0` or `NaN`.223- **Animate SVG wrappers**: Wrap SVG in a `<div>` and animate the wrapper for GPU acceleration.224- **`content-visibility: auto`**: Defer off-screen rendering for long lists.225- **Hydration mismatches**: Use `suppressHydrationWarning` only for expected differences (timestamps, locales). For client-only data (theme), use an inline `<script>` to set the DOM before hydration.226227### JavaScript Performance228229- `Set`/`Map` for repeated lookups instead of array scans230- `toSorted()` / `toReversed()` / `toSpliced()` — `.sort()` mutates231- Combine multiple `.filter()`/`.map()` passes into one loop232- Hoist `RegExp` to module scope; cache `localStorage` reads in a module-level `Map`233234### Advanced Patterns235236- **Initialize once per app load**: Don't put one-time init in `useEffect([], ...)` — it re-runs on remount and runs twice in dev. Use a module-level `let didInit = false` guard.237- **`useEffectEvent`**: Creates a stable function reference that always calls the latest handler, without adding the handler to effect dependencies.238239## Testing Best Practise240241**STOP before writing or reviewing vitest tests** — load [references/testing-best-practices.md](references/testing-best-practices.md) first. It covers the NEVER-do list (untestable files, mock cleanup, loose assertions, testing implementation details, skipping `tsc --noEmit` on test files, and more), the questions to ask before writing a test, the pre-write and test-review workflows, and links to 12 detailed pattern files in `references/testing/` plus the review report template in `assets/testing-output-report-template.md`.242243## Available References244245Detailed documentation available in the `references/` directory:246247- **[useEffect Anti-Patterns](references/useeffect-anti-patterns.md)**: 9 common mistakes with incorrect/correct code examples.248- **[useEffect Alternatives](references/useeffect-alternatives.md)**: `useMemo`, `key` prop, lifting state, `useSyncExternalStore`, event handlers, custom hooks.249- **[TypeScript Do's and Don'ts](references/typescript-dos-and-donts.md)**: Official TypeScript handbook guidance on types, callbacks, and overloads, plus casting/`any`/`unknown` guidance.250- **[Rules of React](references/react-rules.md)**: All four pages of React's official rules — purity, invocation, hooks.251- **[Vercel React Rules](references/vercel-rules/)**: 57 individual rule files with incorrect/correct code examples. Named by category prefix: `async-*`, `bundle-*`, `server-*`, `client-*`, `rerender-*`, `rendering-*`, `js-*`, `advanced-*`. Load individual files on demand rather than the full set.252- **[TanStack Query Reference](references/tanstack-query.md)**: Full API reference for `@tanstack/react-query` v5 — for fallback cases where connect-query is insufficient.253- **[Testing Best Practices](references/testing-best-practices.md)**: Full vitest testing guide — NEVER-do list, pre-write checklist, workflows for writing and reviewing tests, and a table of detailed pattern files.254- **[Vitest Pattern Files](references/testing/)**: 12 files covering organization, AAA pattern, parameterized tests, error handling, assertions, test doubles, async testing, performance, vitest features, snapshot testing, property-based testing, and a quick-start example. Load individual files on demand, per the table in [testing-best-practices.md](references/testing-best-practices.md).255- **[Test Review Report Template](assets/testing-output-report-template.md)**: Standardized format for test code review/audit findings — severity levels, impact analysis, and a summary table.