28 lines
1.8 KiB
Markdown
28 lines
1.8 KiB
Markdown
|
|
# Framework Patterns and Traps
|
||
|
|
|
||
|
|
## React
|
||
|
|
|
||
|
|
- **State updates are async** — `setState(x)` doesn't immediately change state; use callback form for derived state
|
||
|
|
- **Keys must be stable** — Don't use array index as key if list reorders; causes bugs with forms/animations
|
||
|
|
- **useEffect dependencies** — Missing deps cause stale closures; ESLint exhaustive-deps catches these
|
||
|
|
- **useEffect cleanup** — Return cleanup function for subscriptions/timers; prevents memory leaks
|
||
|
|
- **Conditional hooks** — Hooks can't be in conditions/loops; breaks React's hook order tracking
|
||
|
|
- **Context rerenders** — Every consumer rerenders when context value changes; memoize or split contexts
|
||
|
|
|
||
|
|
## Next.js (App Router)
|
||
|
|
|
||
|
|
- **Server vs Client Components** — Default is server; add `"use client"` for hooks, browser APIs, events
|
||
|
|
- **`fetch` in Server Components** — Automatically deduped and cached; use `{cache: 'no-store'}` for fresh
|
||
|
|
- **Middleware runs on edge** — No Node APIs; limited to Web APIs and edge-compatible packages
|
||
|
|
- **Route handlers** — Export `GET`, `POST` functions from `route.ts`; not `page.tsx`
|
||
|
|
- **`revalidatePath`/`revalidateTag`** — Call after mutations to bust cache; ISR invalidation
|
||
|
|
- **Parallel routes** — Use `@folder` convention for loading multiple routes in same layout
|
||
|
|
- **`NEXT_PUBLIC_` prefix** — Required for env vars in client code; others are server-only
|
||
|
|
|
||
|
|
## General SPA
|
||
|
|
|
||
|
|
- **Hydration mismatch** — Server and client must render identically on first pass; use `useEffect` for client-only
|
||
|
|
- **Bundle size** — Tree-shaking needs ES modules; named imports from lodash don't tree-shake without lodash-es
|
||
|
|
- **Code splitting** — Use `lazy()` or `next/dynamic` for below-fold components; improves LCP
|
||
|
|
- **SSR data fetching** — Fetch on server to avoid waterfalls; don't fetch in useEffect for initial data
|