SPB Git

spb/ultra-sharp-agent-skills Public

Ultra-Sharp Agent Skills — a research-first skill-authoring system + 72 production-ready skills for AI agents.

Python 100%

# name: building-react-components description: Designs and writes React components with clean props APIs, composition over configuration, correct state placement, and hooks-based logic reuse. Use when the user asks to create, refactor, or review a React component, design a component API, decide where state should live, extract a custom hook, or fix prop drilling or unnecessary re-renders. Do not use for CSS layout mechanics (designing-responsive-layouts) or non-React frameworks — adapt the principles manually there.

# Building React Components

# When to use / when NOT to use

  • Use for: creating or refactoring React components, designing props APIs, placing state, extracting custom hooks, reviewing component structure.
  • Do NOT use for: CSS layout/breakpoint work (designing-responsive-layouts), styling systems (theming-design-tokens), Vue/Svelte/Angular components, or backend data modeling.

# Core rules

  1. Narrow, typed props — no boolean explosions. One variant union beats three flags that can contradict each other.

    • variant: 'primary' | 'danger' | 'ghost'
    • isPrimary, isDanger, isGhost as three separate booleans
  2. Composition over configuration. When a component grows a prop per content slot, switch to children or slot components.

    • <Card><Card.Header>…</Card.Header><Card.Body>…</Card.Body></Card>
    • <Card headerText="…" headerIcon="…" bodyContent={…} footerButtons={…} />
  3. State lives at the lowest component that needs it; lift only when shared. Before useState, pick the state's home: server data → query library cache; shareable/bookmarkable → URL; everything else → local state closest to use.

    • ✅ search text in the SearchBox, results in the query cache, filters in the URL
    • ❌ every field of a page hoisted into one context "to be safe"
  4. Pick controlled or uncontrolled per input and stay consistent. Controlled (value + onChange) when other UI reacts per keystroke; uncontrolled (defaultValue + read on submit) for plain forms.

    • value without onChange, or switching between the two mid-lifecycle
  5. Extract reusable logic into custom hooks, not wrapper components. A hook named useX returning plain values beats render-props or HOC indirection.

    • const { data, error } = usePolling(url, 5000)
    • <PollingProvider render={(data) => …} />
  6. Memoize only after measuring. No React.memo/useMemo/useCallback by default; add them when the Profiler shows a real re-render cost, and comment why.

    • ❌ wrapping every callback in useCallback "for performance"
  7. One component per file, named exports, file named after the component. UserMenu.tsx exports UserMenu; its private subcomponents stay in the same file until reused elsewhere.

  8. Derive, don't sync. Values computable from existing props/state are computed during render — never mirrored into state with an effect.

    • const fullName = first + ' ' + last
    • useEffect(() => setFullName(first + ' ' + last), [first, last])

# Workflow

  1. Name the component and write its props type first — if the type needs more than ~7 props or any boolean pair, redesign with rules 1–2.
  2. Decide each piece of state's home (rule 3) before writing any useState.
  3. Implement render logic; derive values instead of syncing state (rule 8).
  4. Extract any logic used twice into a custom hook (rule 5).
  5. Self-review: re-check every prop against rules 1–2, every useState against rules 3 and 8, every memoization against rule 6. Fix violations before delivering.

# Edge cases & failure modes

  • Existing codebase conventions conflict with these rules → match the codebase; note the divergence in one sentence, don't refactor uninvited.
  • Class components in the file being edited → keep the class style for small edits; propose (don't perform) a hooks migration.
  • Prop drilling more than 2 levels → prefer composition (pass the composed element down) before reaching for context.
  • Server components (Next.js/RSC) → hooks and state are client-only; add 'use client' only at the interactive leaf, not the page root.

# References

Copy-paste patterns and gotchas: see references/patterns.md