React 19 performance patterns and composition architecture for Vite + Cloudflare projects. 50+ rules ranked by impact โ eliminating waterfalls, bundle optimisation, re-render prevention, composition over boolean props, server/client boundaries, and React 19 APIs. Use when
Installs just this skill. Get the whole plugin for auto-invocation.
โก How it fires
How this skill gets triggered: by you, by Claude, or both.
Fires itselfClaude auto-loads it when your prompt matches the work.
You can call itInvoke it directly when you want it.
Slash command/react-patterns
๐๏ธ Context preview
The summary Claude sees to decide when to auto-load this skill.
React 19 performance patterns and composition architecture for Vite + Cloudflare projects. 50+ rules ranked by impact โ eliminating waterfalls, bundle optimisation, re-render prevention, composition over boolean props, server/client boundaries, and React 19 APIs. Use when
๐ Stats
Stars940
Forks96
LanguagePython
LicenseMIT
๐ฆ Ships with jezweb-skills
</> SKILL.md
react-patterns.SKILL.md
---name: react-patterns
description: "React 19 performance patterns and composition architecture for Vite + Cloudflare projects. 50+ rules ranked by impact โ eliminating waterfalls, bundle optimisation, re-render prevention, composition over boolean props, server/client boundaries, and React 19 APIs. Use when writing, reviewing, or refactoring React components. Triggers: 'react patterns', 'react review', 'react performance', 'optimise components', 'react best practices', 'composition patterns', 'why is it slow', 'reduce re-renders', 'fix waterfall'."
compatibility: claude-code-only
allowed-tools:
- Read
- Glob
- Grep
---# React Patterns
Performance and composition patterns for React 19 + Vite + Cloudflare Workers projects. Use as a checklist when writing new components, a review guide when auditing existing code, or a refactoring playbook when something feels slow or tangled.
Rules are ranked by impact. Fix CRITICAL issues before touching MEDIUM ones.
## When to Apply
- Writing new React components or pages
- Reviewing code for performance issues
- Refactoring components with too many props or re-renders
- Debugging "why is this slow?" or "why does this re-render?"
- Building reusable component libraries
- Code review before merging
## 1. Eliminating Waterfalls (CRITICAL)
Sequential async calls where they could be parallel. The #1 performance killer.
| Pattern | Problem | Fix |
|---------|---------|-----|
| **Await in sequence** | `const a = await getA(); const b = await getB();` | `const [a, b] = await Promise.all([getA(), getB()]);` |
| **Fetch in child** | Parent renders, then child fetches, then grandchild fetches | Hoist fetches to the highest common ancestor, pass data down |
| **Suspense cascade** | Multiple Suspense boundaries that resolve sequentially | One Suspense boundary wrapping all async siblings |
| **Await before branch** | `const data = await fetch(); if (condition) { use(data); }` | Move await inside the branch โ don't fetch what you might not use |
| **Compound components** | Complex component with 15 props | Split into `<Dialog>`, `<Dialog.Trigger>`, `<Dialog.Content>` with shared context |
| **renderX props** | `<Layout renderSidebar={...} renderHeader={...} renderFooter={...}>` | Use children + named slots: `<Layout><Sidebar /><Header /></Layout>` |
| **Lift state** | Sibling components can't share state | Move state to parent or context provider |
| **Provider implementation** | Consumer code knows about state management internals | Provider exposes interface `{ state, actions, meta }` โ implementation hidden |
| **Inline components** | `function Parent() { function Child() { ... } return <Child /> }` | Define Child outside Parent โ inline components remount on every render |
**The test**: If a component has more than 5 boolean props, it needs composition, not more props.
## 4. Re-render Prevention (MEDIUM)
Not all re-renders are bad. Only fix re-renders that cause visible jank or wasted computation.
| Pattern | Problem | Fix |
|---------|---------|-----|
| **Default object/array props** | `function Foo({ items = [] })` โ new array ref every render | Hoist: `const DEFAULT = []; function Foo({ items = DEFAULT })` |
| **Derived state in effect** | `useEffect(() => setFiltered(items.filter(...)), [items])` | Derive during render: `const filtered = useMemo(() => items.filter(...), [items])` |
| **Object dependency** | `useEffect(() => {...}, [config])` fires every render if config is `{}` | Use primitive deps: `useEffect(() => {...}, [config.id, config.type])` |
| **Subscribe to unused state** | Component reads `{ user, theme, settings }` but only uses `user` | Split context or use selector: `useSyncExternalStore` |
| **State for transient values** | `const [mouseX, setMouseX] = useState(0)` on mousemove | Use `useRef` for values that change frequently but don't need re-render |
| **Inline callback props** | `<Button onClick={() => doThing(id)} />` โ new function every render | `useCallback` or functional setState: `<Button onClick={handleClick} />` |
**How to find them**: React DevTools Profiler โ "Why did this render?" or `<React.StrictMode>` double-renders in dev.