
React Patterns
- 1.1k installs
- 946 repo stars
- Updated July 2, 2026
- jezweb/claude-skills
react-patterns is a Claude Code skill that applies 50+ ranked React 19 performance and composition rules when developers write, review, or refactor components in Vite and Cloudflare projects.
About
react-patterns is a Claude Code-only skill from jezweb/claude-skills packing 50+ React 19 rules ranked by impact for Vite and Cloudflare frontends. It targets eliminating request waterfalls, bundle optimization, re-render prevention, composition over boolean props, server and client boundaries, and React 19 APIs when creating, reviewing, or refactoring components. The skill uses Read, Glob, and Grep to inspect codebases and fires on triggers like react performance, reduce re-renders, fix waterfall, and composition patterns. Developers reach for react-patterns when components feel slow, prop drilling grows unwieldy, or a React review needs impact-ordered fixes instead of generic style advice.
- 50+ rules ranked by impact with CRITICAL, MEDIUM and LOW severity tiers
- Eliminates waterfalls by converting sequential async calls to parallel
- Prevents unnecessary re-renders using composition over boolean props
- Enforces correct React 19 server/client boundaries and new APIs
- Serves as writing checklist, code review guide, and refactoring playbook
React Patterns by the numbers
- 1,076 all-time installs (skills.sh)
- +27 installs in the week ending Jul 29, 2026 (Skillselion tracking)
- Ranked #346 of 2,244 Frontend Development skills by installs in the Skillselion catalog
- Security screen: LOW risk (skills.sh audit)
- Data as of Jul 31, 2026 (Skillselion catalog sync)
npx skills add https://github.com/jezweb/claude-skills --skill react-patternsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1.1k |
|---|---|
| repo stars | ★ 946 |
| Security audit | 3 / 3 scanners passed |
| Last updated | July 2, 2026 |
| Repository | jezweb/claude-skills ↗ |
How do you fix React 19 performance bottlenecks in Vite apps?
Apply React 19 performance patterns and composition architecture when creating, reviewing or refactoring components in Vite + Cloudflare projects.
Who is it for?
Frontend developers building or reviewing React 19 components in Vite and Cloudflare projects who need performance-first, composition-oriented guidance.
Skip if: Backend-only API work, non-React frameworks, or teams not using Vite or Cloudflare deployment targets.
When should I use this skill?
The user mentions react patterns, react review, react performance, optimise components, reduce re-renders, fix waterfall, or composition patterns.
What you get
Impact-ranked refactor recommendations, optimized component composition, and reduced re-render and waterfall issues in React 19 code.
- Performance refactor recommendations
- Composition architecture fixes
By the numbers
- Includes 50+ React 19 rules ranked by impact
- Uses Read, Glob, and Grep as allowed inspection tools
Files
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 |
| Import then render | const Component = await import('./Heavy'); return <Component /> | Use React.lazy() + <Suspense> — renders fallback instantly |
How to find them: Search for await in components. Each await is a potential waterfall. If two awaits are independent, they should be parallel.
2. Bundle Size (CRITICAL)
Every KB the user downloads is a KB they wait for.
| Pattern | Problem | Fix |
|---|---|---|
| Barrel imports | import { Button } from '@/components' pulls the entire barrel file | import { Button } from '@/components/ui/button' — direct import |
| No code splitting | Heavy component loaded on every page | React.lazy(() => import('./HeavyComponent')) + <Suspense> |
| Third-party at load | Analytics/tracking loaded before the app renders | Load after hydration: useEffect(() => { import('./analytics') }, []) |
| Full library import | import _ from 'lodash' (70KB) | import debounce from 'lodash/debounce' (1KB) |
| Lucide tree-shaking | import * as Icons from 'lucide-react' (all icons) | Explicit map: import { Home, Settings } from 'lucide-react' |
| Duplicate React | Library bundles its own React → "Cannot read properties of null" | resolve.dedupe: ['react', 'react-dom'] in vite.config.ts |
How to find them: npx vite-bundle-visualizer — shows what's in your bundle.
3. Composition Architecture (HIGH)
How you structure components matters more than how you optimise them.
| Pattern | Problem | Fix |
|---|---|---|
| Boolean prop explosion | <Card isCompact isClickable showBorder hasIcon isLoading> | Explicit variants: <CompactCard>, <ClickableCard> |
| 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.
5. React 19 Specifics (MEDIUM)
Patterns that changed or are new in React 19.
| Pattern | Old (React 18) | New (React 19) |
|---|---|---|
| Form state | useFormState | useActionState — renamed |
| Ref forwarding | forwardRef((props, ref) => ...) | function Component({ ref, ...props }) — ref is a regular prop |
| Context | useContext(MyContext) | use(MyContext) — works in conditionals and loops |
| Pending UI | Manual loading state | useTransition + startTransition for non-urgent updates |
| Route-level lazy | Works with createBrowserRouter only | Still true — <Route lazy={...}> is silently ignored with <BrowserRouter> |
| Optimistic updates | Manual state management | useOptimistic hook |
| Metadata | Helmet or manual <head> management | <title>, <meta>, <link> in component JSX — hoisted to <head> automatically |
6. Rendering Performance (MEDIUM)
| Pattern | Problem | Fix |
|---|---|---|
| Layout shift on load | Content jumps when async data arrives | Skeleton screens matching final layout dimensions |
| Animate SVG directly | Janky SVG animation | Wrap in <div>, animate the div instead |
| Large list rendering | 1000+ items in a table/list | @tanstack/react-virtual for virtualised rendering |
| content-visibility | Long scrollable content renders everything upfront | content-visibility: auto on off-screen sections |
| Conditional render with && | {count && <Items />} renders 0 when count is 0 | Use ternary: {count > 0 ? <Items /> : null} |
7. Data Fetching (MEDIUM)
| Pattern | Problem | Fix |
|---|---|---|
| No deduplication | Same data fetched by 3 components | TanStack Query or SWR — automatic dedup + caching |
| Fetch on mount | useEffect(() => { fetch(...) }, []) — waterfalls, no caching, no dedup | TanStack Query: useQuery({ queryKey: ['users'], queryFn: fetchUsers }) |
| No optimistic update | User clicks save, waits 2 seconds, then sees change | useMutation with onMutate for instant visual feedback |
| Stale closure in interval | setInterval captures stale state | useRef for the interval ID and current values |
| Polling without cleanup | setInterval in useEffect without clearInterval | Return cleanup: useEffect(() => { const id = setInterval(...); return () => clearInterval(id); }) |
8. Vite + Cloudflare Specifics (MEDIUM)
| Pattern | Problem | Fix |
|---|---|---|
| `import.meta.env` in Node scripts | Undefined — only works in Vite-processed files | Use loadEnv() from vite |
| React duplicate instance | Library bundles its own React | resolve.dedupe + optimizeDeps.include in vite.config.ts |
| Radix Select empty string | <SelectItem value=""> throws | Use sentinel: <SelectItem value="__any__"> |
| React Hook Form null | {...field} passes null to Input | Spread manually: value={field.value ?? ''} |
| Env vars at edge | process.env doesn't exist in Workers | Use c.env (Hono context) or import.meta.env (Vite build-time) |
Using as a Review Checklist
When reviewing code, go through categories 1-3 (CRITICAL + HIGH) for every PR. Categories 4-8 only when performance is a concern.
/react-patterns [file or component path]Read the file, check against rules in priority order, report findings as:
file:line — [rule] description of issueRelated skills
How it compares
Pick react-patterns over generic React lint skills when you need impact-ranked React 19 performance fixes for Vite and Cloudflare rather than syntax-only review.
FAQ
How many rules does react-patterns include?
react-patterns includes 50+ React 19 performance and composition rules ranked by impact, covering waterfalls, bundle optimization, re-renders, and server/client boundaries for Vite and Cloudflare projects.
Which stacks does react-patterns target?
react-patterns targets React 19 with Vite bundling and Cloudflare deployment, applying composition architecture and performance fixes during component writing, review, and refactoring.
Is React Patterns safe to install?
skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.