Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Use this skill when you’re building or refactoring React components in a production app and want **consistent patterns** for typing, composition, state, and performance without introducing premature abstraction.
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | -9% | 0% |
| case-19 | ✗→✓ | ▲ Improved | 18% | 0% |
| case-09 | ✓→✗ | ▼ Worse | -28% | 0% |
| case-18 | ✓→✓ | = Same ✓ | 21% | 0% |
| case-03 | ✓→✓ | = Same ✓ | 29% | 0% |
Use this skill when you’re building or refactoring React components in a production app and want consistent patterns for typing, composition, state, and performance without introducing premature abstraction.
...rest unless you’re building a wrapper that truly forwards).Example:
tsxexport interface ButtonProps { variant?: "primary" | "secondary"; disabled?: boolean; onClick?: () => void; children: React.ReactNode; } export function Button({ variant = "primary", disabled, onClick, children }: ButtonProps) { return ( <button data-variant={variant} disabled={disabled} onClick={onClick}> {children} </button> ); }
type)interface for public component props (extends well, readable in IDEs).type for unions, helpers, and composition.Patterns:
interface XProps { ... }type Variant = "a" | "b"type Props = XProps & { ... } when combining.Controlled inputs make state explicit and testable.
Pattern:
value + onChange(next).tsxexport interface TextFieldProps { value: string; onChange: (next: string) => void; label?: string; } export function TextField({ value, onChange, label }: TextFieldProps) { return ( <label> {label} <input value={value} onChange={(e) => onChange(e.target.value)} /> </label> ); }
For components/Foo/:
Foo.tsx (component)Foo.test.tsx (tests)Foo.stories.tsx (storybook if used)types.ts (shared types) only if it growsAvoid:
index.ts barrels that hide importsRules:
use.[value, setValue]).tsexport function useDisclosure(initial = false) { const [open, setOpen] = React.useState(initial); return { open, openNow: () => setOpen(true), close: () => setOpen(false), toggle: () => setOpen((v) => !v), }; }
Most apps do not need useMemo/useCallback everywhere.
Use memoization when:
useEffect / subscriptionsAvoid memoization when:
memo, useMemo, useCallback: when they helpGuideline:
Common anti-pattern:
useCallback “just in case”Use React Context for:
Avoid Context for:
If you need app-wide, high-frequency state:
Options in order:
Pattern:
<Menu> provides context<Menu.Button> and <Menu.Items> consume itBenefits:
Render props are useful when you want to expose internal state without forcing component structure. Prefer hooks first; use render props when you need to interleave layout and control.
grep/glob to find component usage patterns; use read_file to inspect existing props and state flow.edit_file, then run tests.grep/glob to locate entry points and affected components, then read them with read_file.run_command (Build mode) to run vitest/playwright or the project’s test scripts.When reviewing a component, check:
useMemo/useCallback everywhere “for performance” without measuringany in props; prefer precise unions and unknown where neededOther measured skills in the registry, with their headline benchmark lift.