Install any skill in seconds. Free to start, no credit card required.
Get Started Free →jezweb/react-patterns
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.
Passed 23 of 24 test cases with the skill, and 20 of 24 without it.
3 fixed20 passed either way1 still failing0 broke
Tokens, turns and time describe resource use, not a dollar price.
One of 3 test cases the skill fixed. Same model, same prompt, with and without the skill.
When rendering a list count with `{count && <ListItems />}` in JSX, what visual bug happens when `count` is `0`, and how should the condition be written?
| Checked | Without skill | With skill |
|---|---|---|
| Explains that 0 renders literal string 0 into DOM | Passed | Passed |
| Replaces logical AND with ternary operator condition count > 0 ? <ListItems /> : null | Missed | Passed |
The instructions your model reads when the skill loads.
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.
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.
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' |
test cases passed, vs 20 / 24 without
Published skills whose descriptions closely match this one, with their headline benchmark lift.
More skills from the same source and nearby in the registry, with their headline benchmark lift.