Install any skill in seconds. Free to start, no credit card required.
Get Started Free →React component patterns, forms, accessibility, and responsive design. Use when building React components, handling forms, or ensuring accessibility. Triggers on: React component, useEffect, form validation, a11y, responsive, Error Boundary.
.claude/skills/aiskillstore-pitfalls-react/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 16% | 0% |
| case-03 | ✗→✓ | ▲ Improved | -21% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 17% | 0% |
| case-05 | ✓→✓ | = Same ✓ | 33% | 0% |
| case-06 | ✓→✓ | = Same ✓ | 63% | 0% |
Common pitfalls and correct patterns for React development.
Verify loading/error states and data checks.
Ensure Zod schemas and proper error display.
Verify ARIA labels and keyboard navigation.
tsx// ✅ Define helpers before use or as exports function formatPrice(price: number) { ... } export default function Component() { // ✅ Check data exists before accessing if (!data) return <Loading />; // ✅ useEffect for side effects only useEffect(() => { fetchData(); }, []); // ✅ data-testid on interactive elements return <button data-testid="submit-btn">Submit</button>; } // ❌ WRONG: Defining function in render return <button onClick={() => { function doSomething() { } // Don't define here doSomething(); }}> // ✅ Navigation with router, not window import { Link, useLocation } from 'wouter'; <Link to="/dashboard">Go</Link> // ❌ window.location.href = '/dashboard'
tsx// ✅ Wrap major components in error boundaries class ErrorBoundary extends React.Component { state = { hasError: false, error: null }; static getDerivedStateFromError(error) { return { hasError: true, error }; } componentDidCatch(error, info) { logError({ error, componentStack: info.componentStack }); } render() { if (this.state.hasError) { return <ErrorFallback onRetry={() => this.setState({ hasError: false })} />; } return this.props.children; } } // ✅ Graceful degradation function Dashboard() { const { data, error, isLoading } = useQuery(...); if (isLoading) return <Skeleton />; if (error) return <ErrorCard message="Unable to load" onRetry={refetch} />; if (!data) return <EmptyState />; return <DashboardContent data={data} />; }
typescript// ✅ Zod schemas for all forms const createStrategySchema = z.object({ name: z.string().min(1, 'Name required').max(100), type: z.enum(['cross-exchange', 'triangular']), minProfit: z.number().positive('Must be positive'), }); // ✅ React Hook Form with Zod const form = useForm<z.infer<typeof createStrategySchema>>({ resolver: zodResolver(createStrategySchema), }); // ✅ Show errors inline {errors.name && <span className="text-red-500">{errors.name.message}</span>} // ✅ Disable submit while validating/submitting <button disabled={isSubmitting || !isValid}>Submit</button>
css/* ✅ Mobile-first breakpoints */ .container { padding: 1rem; } @media (min-width: 768px) { .container { padding: 2rem; } } /* ✅ Touch-friendly button sizes (min 44px) */ .btn { min-height: 44px; min-width: 44px; } /* ✅ Horizontal scroll for data tables on mobile */ .table-container { overflow-x: auto; }
tsx// ✅ Semantic HTML <nav>...</nav> <main>...</main> <button>Click me</button> // Not <div onClick> // ✅ ARIA labels <button aria-label="Close dialog">×</button> // ✅ Keyboard navigation <button onKeyDown={(e) => e.key === 'Enter' && handleClick()}> // ✅ Focus indicators button:focus { outline: 2px solid blue; outline-offset: 2px; }
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-05 | pass→pass | 12,769 | 10,934 | -14% | 1 | 1 | 0% | 2,338 | 3,110 | +33% | 0 | 0 | — |
case-01 | fail→pass | 21,413 | 17,284 | -19% | 1 | 1 | 0% | 2,997 | 3,462 | +16% | 0 | 0 | — |
case-02 | fail→fail | 34,461 | 28,300 | -18% | 1 | 1 | 0% | 7,668 | 7,308 | -5% | 0 | 0 | — |
case-03 | fail→pass | 34,797 | 22,167 | -36% | 1 | 1 | 0% | 7,830 | 6,183 | -21% | 0 | 0 | — |
case-04 | fail→pass | 16,750 | 8,364 | -50% | 1 | 1 | 0% | 2,057 | 2,415 | +17% | 0 | 0 | — |
case-06 | pass→pass | 10,938 | 17,900 | +64% | 1 | 1 | 0% | 2,240 | 3,652 | +63% | 0 | 0 | — |
case-07 | pass→pass | 10,944 | 3,034 | -72% | 1 | 1 | 0% | 2,002 | 1,478 | -26% | 0 | 0 | — |
case-08 | pass→pass | 10,710 | 11,969 | +12% | 1 | 1 | 0% | 1,984 | 2,497 | +26% | 0 | 0 | — |
case-09 | pass→pass | 18,937 | 7,539 | -60% | 1 | 1 | 0% | 2,342 | 2,320 | -1% | 0 | 0 | — |
case-22 | pass→pass | 13,888 | 20,400 | +47% | 1 | 1 | 0% | 1,628 | 2,086 | +28% | 0 | 0 | — |
case-10 | pass→pass | 18,608 | 16,749 | -10% | 1 | 1 | 0% | 2,403 | 3,155 | +31% | 0 | 0 | — |
case-11 | pass→pass | 11,266 | 3,284 | -71% | 1 | 1 | 0% | 1,118 | 1,487 | +33% | 0 | 0 | — |
case-12 | pass→pass | 20,297 | 12,066 | -41% | 1 | 1 | 0% | 2,630 | 2,163 | -18% | 0 | 0 | — |
case-13 | pass→pass | 8,145 | 7,681 | -6% | 1 | 1 | 0% | 522 | 1,418 | +172% | 0 | 0 | — |
case-14 | pass→pass | 13,403 | 7,052 | -47% | 1 | 1 | 0% | 2,254 | 2,228 | -1% | 0 | 0 | — |
case-15 | pass→pass | 18,434 | 7,587 | -59% | 1 | 1 | 0% | 2,472 | 2,464 | -0% | 0 | 0 | — |
case-16 | pass→pass | 22,524 | 13,852 | -39% | 1 | 1 | 0% | 2,637 | 3,429 | +30% | 0 | 0 | — |
case-17 | pass→pass | 20,355 | 9,157 | -55% | 1 | 1 | 0% | 2,909 | 2,799 | -4% | 0 | 0 | — |
case-18 | pass→pass | 19,082 | 12,336 | -35% | 1 | 1 | 0% | 2,437 | 3,040 | +25% | 0 | 0 | — |
case-19 | pass→pass | 12,524 | 8,795 | -30% | 1 | 1 | 0% | 2,098 | 1,661 | -21% | 0 | 0 | — |
case-20 | pass→pass | 21,990 | 15,908 | -28% | 1 | 1 | 0% | 2,113 | 3,481 | +65% | 0 | 0 | — |
case-21 | pass→pass | 22,975 | 15,019 | -35% | 1 | 1 | 0% | 2,347 | 2,934 | +25% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +14 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.