agentsclimarketplace

React expert

Skill Akayashuu/agent-skills/skills/react-expert

Framework & language expert skills for Claude Code — idiomatic best practices for TypeScript, React, Vue, Svelte, Solid, Angular, Astro

Install
npx -y skills add Akayashuu/agent-skills --skill react-expert

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Use when writing, reviewing, or refactoring React components — taming re-renders, deciding what belongs in state vs derived during render, fixing useEffect overuse/race conditions, key/list bugs, useMemo/useCallback noise, context, refs, or server vs client component ("use client") boundaries.

SKILL.md

7.3 KB, as published. Nobody here has run it

React Expert

Overview

Idiomatic React is derive, don't store; render, don't sequence. Most state is redundant and most effects are a smell — the UI is a pure function of props, state, and context, and useEffect exists only to sync with systems outside React. These are the judgment calls a linter can't make for you.

Quick Reference

GoalDoAvoid
Value computable from props/statecompute in renderuseState + useEffect to "keep it updated"
React to a prop/state changederive in render, or key to resetuseEffect watching that value
Talk to a non-React systemuseEffect (subscriptions, DOM, timers)effects for data transforms
List itemsstable id keykey={index}
Fetch dataframework / TanStack Query / RSChand-rolled useEffect + fetch
Avoid prop-drillingcomposition (children) then contextone giant global context
Expensive recompute / referential depuseMemo/useCallback with a real reasonmemoizing everything by default
Form inputcontrolled, or uncontrolled + refmixing both on one field
Read latest props/state inside an EffectuseEffectEvent (stable in 19.2)widening effect deps to silence the linter

Core Patterns

Derive during render — don't mirror props/state into an effect. The effect runs after paint, so the UI flashes a stale value, and the extra render is pure waste:

// ❌ redundant state + effect: extra render, stale frame, easy to desync
function Cart({ items }: { items: Item[] }) {
  const [total, setTotal] = useState(0)
  useEffect(() => { setTotal(items.reduce((s, i) => s + i.price, 0)) }, [items])
  return <p>{total}</p>
}
// ✅ it's just a value; compute it. Wrap in useMemo only if profiling says so.
const total = items.reduce((s, i) => s + i.price, 0)

Runnable: examples/derive-during-render.tsx

Reset state on identity change with key, not an effect. Changing the key remounts the subtree, discarding old state — no manual resync:

// ❌ effect to "reset form when user changes" — stale between switch and effect
useEffect(() => { setDraft('') }, [userId])
// ✅ a different user is a different form; let React remount it
<ProfileForm key={userId} />

Runnable: examples/reset-with-key.tsx

Effects are for external systems — and must clean up to dodge races. Anything async needs an ignore flag or AbortController, which is exactly why a data library is better:

// ❌ no cleanup: a slow earlier request resolves last and overwrites the new one
useEffect(() => { fetch(`/api/u/${id}`).then(r => r.json()).then(setUser) }, [id])
// ✅ ignore stale resolutions (or just use TanStack Query / an RSC loader)

Runnable: examples/abortable-effect-fetch.tsx

Composition kills prop-drilling before context does. Pass rendered UI as children so intermediate components never see props they only forward:

// ❌ Layout threads `user` through just to hand it down
<Layout user={user} />  // Layout forwards user → Sidebar → Avatar
// ✅ render the leaf where the data lives; Layout stays agnostic
<Layout sidebar={<Avatar user={user} />} />

Separate non-reactive logic with useEffectEvent — don't lie to the deps array. Stable since React 19.2: an Effect Event always sees the latest props/state but isn't reactive, so it stays out of the deps array — for fresh values an Effect shouldn't re-synchronize on:

const onConnected = useEffectEvent(() => log('connected', theme)) // reads latest theme
useEffect(() => {
  const conn = createConnection(roomId)
  conn.on('connected', () => onConnected())
  conn.connect()
  return () => conn.disconnect()
}, [roomId]) // re-runs on roomId only; theme change does NOT reconnect

Runnable: examples/use-effect-event.tsx

Memoize for referential stability, not "speed." A useCallback/useMemo matters when its result is a dependency of a memoized child or another hook — otherwise it's noise that adds its own cost:

const onSelect = useCallback((id: string) => dispatch(select(id)), [dispatch]) // stable prop for memo'd <Row>

React Compiler (1.0, stable Oct 2025) changes this calculus. It auto-memoizes at build time, so with the compiler on you can delete most hand-written useMemo/useCallback/React.memo. Keep them only where it bails out (components that break the Rules of React). The compiler optimizes; it won't fix stored derived state or over-broad effect deps.

Common Mistakes

  • useEffect to compute derived data — transform in render; effects are for syncing with the outside world.
  • key={index} — on reorder/insert, React reuses the wrong DOM/state. Use a stable id.
  • Stale closures — a callback captures the render's values; reading "latest" inside an Effect is what useEffectEvent is for — not a lie to the deps array.
  • Over-broad or missing deps — don't silence react-hooks/exhaustive-deps; fix the design (move logic out, use a ref, or a functional setState(prev => …)).
  • setState during render without a guard → infinite loop. Derive instead.
  • Premature memo/useMemo everywhere — measure first; memoization isn't free.
  • One giant context — every consumer re-renders on any field change. Split by concern (or by state vs dispatch).
  • ref for things render should own — refs are an imperative escape hatch (focus, measure, integrate non-React libs), not a place to stash render data.
  • Reading data in a Server Component then marking the whole tree 'use client' — keep 'use client' at the interactive leaf; fetch on the server.

When NOT to over-engineer

Local, cheap, self-contained UI state (a toggle, an input) needs no reducer, no context, no memo. Reach for useReducer, context splitting, or a data library when state is shared, complex, or async — not preemptively. In React 19 (stable), prefer the platform: use to unwrap promises/context, <form> Actions + useActionState for submission and pending UI, useOptimistic for optimistic updates, ref-as-prop (no more forwardRef), and Server Components to fetch on the server so the client ships less and avoids effect-based fetching entirely. Don't hand-roll what the framework now does.

See examples/ for self-contained, compiling versions of each pattern above (and patterns.tsx for the same three combined in one module).

Sources

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.