Install
$ agentstack add skill-xobotyi-cc-foundry-react ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
React
Components are pure functions. State is minimal. Effects are escape hatches. If you reach for useEffect, verify you actually need it.
React rewards thinking in components: break UI into pieces, find minimal state, identify where it lives, and wire data flow from parent to child. References contain extended examples, rationale, and edge cases for each topic area.
References
- Components —
${CLAUDE_SKILL_DIR}/references/components.mdComposition, refs, metadata, custom elements - Hooks —
${CLAUDE_SKILL_DIR}/references/hooks.mdHook rules, custom hooks,useSyncExternalStore - State —
${CLAUDE_SKILL_DIR}/references/state.mdPlacement, reducers, context, actions - Performance —
${CLAUDE_SKILL_DIR}/references/performance.mdCompiler, memoization, server components, streaming - Testing —
${CLAUDE_SKILL_DIR}/references/testing.mdQuery priority/variants, userEvent catalog, async patterns
Component Design
Thinking in React
Build UI in five steps:
- Break UI into a component hierarchy — each component does one thing.
- Build a static version first — props only, no state, no interactivity.
- Find minimal state — if it doesn't change, is passed from a parent, or can be computed, it is not state.
- Identify where state lives — find every component that renders based on the state, find their closest common parent,
put state there.
- Add inverse data flow — pass state-setter callbacks down so children update parent state through event handlers.
Purity
React assumes every component is a pure function. Same props + same state = same JSX. Never mutate props, state, or variables declared before rendering.
- Local mutation is fine. Creating and mutating objects/arrays within the same render is safe — the mutation is
invisible outside that render.
- Event handlers don't need to be pure — they run outside of rendering.
Component Structure
- One component per file. Small helpers co-located in the same file are acceptable but extract when reused.
- Prefer function declarations for components.
- Do not use
React.FC— it adds implicitchildrentyping and complicates generics. Use
function Component(props: Props).
Component Body Organization
Separate logic from rendering. The component body handles computation, state, and handler definitions. JSX is declarative — it references results, not processes.
- Handler object — group all event handlers in a single
handleobject. This creates a clear boundary between logic
and rendering: ``tsx const handle = { submit() { /* ... */ }, inputChange(e: ChangeEvent) { setName(e.target.value); }, keyDown(e: KeyboardEvent) { if (e.key === 'Enter') handle.submit(); }, }; ` Reference in JSX as onChange={handle.inputChange}`. Never inline handler logic in JSX.
- Pre-render computation — move list rendering and derived JSX out of the return statement into component body
variables: ``tsx const tabElements: ReactNode[] = []; for (const tab of allTabs) { tabElements.push({tab.name}); } return {tabElements}; ` JSX .map()` inside the return statement is discouraged — compute element arrays in the body, reference them in JSX.
- Conditional rendering — simple conditions (
{isVisible && }) are acceptable inline in JSX. When the
condition is complex or involves multiple branches, compute the result in the component body and reference the variable in JSX.
Composition
- Props flow down, events flow up. One-way data flow. Children never mutate parent state directly — they call callbacks.
- Composition over configuration. Pass JSX as
childrenor render props instead of building components with dozens of
boolean flags.
- When a wrapper component updates its own state, React knows its
childrenprops haven't changed, so children skip
re-rendering.
- Use compound components (shared context between related sub-components) for complex UI patterns like flyout menus,
tabs, accordions.
- Prefer controlled components when parent needs to coordinate state across siblings. Prefer uncontrolled for isolated,
self-contained UI.
Refs
refis a prop. Passrefdirectly as a prop to function components. Never useforwardRef— it is deprecated.- Ref callbacks can return a cleanup function, called when the element unmounts.
- Avoid implicit returns in ref callbacks — use block body
{}not parentheses to prevent TypeScript confusion.
Document Metadata
Render `, , directly in components. React hoists them to ` automatically. Works with client-only apps, streaming SSR, and Server Components.
Custom Elements
React provides full custom element support. Server rendering: primitive props render as attributes, non-primitive props are omitted. Client rendering: props matching element instance properties are assigned as properties, others as attributes.
JSX Conventions
- Self-closing tags for components without children: ``.
- Boolean attributes without value: `
notdisabled={true}`. - Fragments to avoid wrapper divs:
<>...or ``. - Avoid
&&with numbers —count &&renders0. Usecount > 0 &&or a ternary. - Never inline handler logic in JSX. Group all handlers in a
handleobject in the component body (see Component Body
Organization).
- Spread props sparingly —
{...props}makes it unclear what a component accepts. Prefer explicit props. keyon every list item. Stable, unique identifiers. Never use array index as key when items can reorder.- No side effects during render. Event handlers for user actions, Effects for synchronization, render for pure
computation.
Hooks
use() — Context and Promises
- Prefer
use(MyContext)overuseContext(MyContext).use()can be called inside conditionals and loops —
useContext() cannot.
use()always looks for the closest provider above the calling component.use(promise)integrates with Suspense and Error Boundaries to read promise values.- Do not create promises inside Client Components during render — they recreate every render. Pass promises from Server
Components or use a Suspense-compatible library.
- In Server Components, prefer
async/awaitoveruse(). use()cannot be called in a try-catch block. Use Error Boundaries orpromise.catch()instead.
Hook Rules
- Top level only. Never call hooks inside conditions, loops, or nested functions. React relies on call order. Exception:
use() can be called conditionally.
- React functions only. Call hooks from function components or custom hooks — never from regular JavaScript functions.
- Exhaustive deps. Include all reactive values used inside the Effect in the dependency array. The linter enforces this
— don't suppress it. If a dependency causes unwanted re-runs, restructure the code.
- One Effect per concern. Don't merge unrelated sync logic into a single Effect. Separate Effects for separate external
systems.
Effects Are Escape Hatches
Use Effects only to synchronize with external systems (DOM APIs, network, browser events). Not for transforming data, handling user events, or state derivation.
You don't need an Effect for:
- Transform data for rendering — Compute during render
- Handle user events — Call in event handler
- Reset state on prop change — Use
key={userId}on the component - Adjust state on prop change — Compute:
items.find(...)during render - Notify parent of state change — Call
onChangein the event handler - Share logic between handlers — Extract a function, call from both handlers
- Chain state updates — Calculate all state in one event handler
You DO need an Effect for:
- Subscribing to browser events (online/offline, resize, intersection)
- Connecting to external systems (WebSocket, third-party widgets)
- Fetching data that depends on current props/state (with cleanup)
- Synchronizing with non-React DOM (imperative animations, canvas)
Every Effect that subscribes must return a cleanup function. Data fetching in Effects must use a cleanup flag (let ignore = false) to prevent race conditions. Prefer a data-fetching library or use() with Suspense over raw Effects for fetching.
Custom Hooks
- Custom hooks share stateful logic, not state itself. Each call creates independent state.
- Must start with
usefollowed by a capital letter. Functions that don't call hooks should NOT start withuse. - Name after the use case, not the lifecycle —
useOnlineStatusnotuseMount. - Extract when: repetitive Effect logic across components, complex state + Effect combos, or synchronization with
external systems.
- Don't extract a single
useStateinto a hook — that's unnecessary abstraction.
Return value conventions:
- Single value: return directly (
return isOnline) - Value + setter pair: return tuple (
return [value, setValue] as const) - Multiple related values: return object (
return { value, onChange, reset })
useSyncExternalStore
For subscribing to external data stores, prefer useSyncExternalStore over manual Effect + state. Provide a subscribe function, a client snapshot getter, and a server snapshot getter for SSR.
State Management
State Placement Decision Tree
- Does only one component use it? Keep it local with
useState. - Do siblings need it? Lift to their closest common parent.
- Is prop drilling painful (5+ levels)? Try composition first — restructure components to pass JSX as
children. - Still painful after composition? Use Context with
use(). - Is it server data? Use a data-fetching library — not
useState+useEffect.
Local state → Lift state up → Composition → Context → External library
Server Cache vs UI State
- UI state (modal open, form input, selected tab) —
useState,useReducer, Context - Server cache (user data, search results, API responses) — react-query, SWR, framework loaders
Never reinvent caching, deduplication, and race condition handling with raw useState.
useState
- Minimal state. If it can be computed from existing props or state, compute it during render — don't store it.
- Colocate state. Keep state as close to where it's used as possible. Lift up only when multiple components need it.
- Use updater functions when next state depends on previous state:
setCount(prev => prev + 1)not
setCount(count + 1).
- Lazy initialization for expensive initial values — pass a function:
useState(() => createInitialState())not
useState(createInitialState()).
useReducer
Use when state updates are complex — many event handlers modifying the same state, or when next state depends on previous state in non-trivial ways.
- Single value, simple updates —
useState - Multiple related values, complex transitions —
useReducer - Many event handlers doing similar state updates —
useReducer - Need to test state logic in isolation —
useReducer
Reducer rules:
- Reducers must be pure — same inputs = same output, no side effects.
- Each action describes a single user interaction — dispatch
reset_formnot five separateset_fieldactions. - Actions describe what happened, not what to do —
'added_task'not'set_tasks'. - Always have a
defaultcase that throws to catch typos early. - Use
as constfor action types in TypeScript.
key for Identity Reset
Use key to reset a component's state when the conceptual entity changes: ``. This is cleaner than using an Effect to reset state on prop change.
Context
- Use `
directly — not`. - Always wrap context consumption in a custom hook with a null check that throws if used outside the provider.
- Try props and composition first. Context is not the first solution to prop drilling.
- Keep context close to where it's used — not every context belongs at the app root.
- Split logically — user settings separate from notifications. Don't put all state in one giant context.
- Different
createContext()calls are independent — they don't override each other. - For complex shared state, combine
useReducerwith context. Split into two contexts (data + dispatch) so components
that only dispatch don't re-render on data changes.
Actions
- Use
useActionStatefor form submissions and data mutations. It manages pending state, errors, and sequential action
queuing automatically.
- When passed to ``, React wraps submission in a transition automatically. When calling dispatch manually,
wrap in startTransition.
- Return error states instead of throwing to prevent skipping queued actions.
- Use
useOptimisticfor instant UI feedback while async Actions complete. The optimistic state reverts to real value
when the Action completes or fails.
- Use a reducer form of
useOptimisticfor complex updates (e.g., adding to a list). useFormStatusreads submission status of the nearest parent `` — must be called from a component rendered
inside a ``, not in the same component.
TypeScript
- Every component with props must have a dedicated named type (e.g.,
ButtonProps). Never define prop types inline in
the function signature. Use function Button(props: ButtonProps) or destructure: function Button({ label }: ButtonProps).
- Don't use
React.FC. Use plain function declarations. - Type events explicitly when needed:
(e: React.ChangeEvent) => void. - Use
as constfor action types in reducers.
Performance
React Compiler
React Compiler is a build-time tool that automatically applies memo, useMemo, and useCallback equivalents. When using the compiler:
- Do not manually wrap components in
memo, useuseMemo, oruseCallbackin new code. - Leave existing memoization in place — removing it can change compilation output.
- Use manual memoization only as an escape hatch (e.g., stabilizing an Effect dependency).
- The compiler works with plain JavaScript and the Rules of React — no code changes needed.
Optimization Decision Tree
- Is there a perceptible lag? No — don't optimize.
- Is the render itself slow? Profile it. Fix the computation.
- Are components re-rendering unnecessarily? Restructure first (push state down, lift content up).
- Still slow after restructuring? Apply
memo,useMemo,useCallback.
Fix the slow render before you fix the re-render. Restructuring beats memoization.
Manual Memoization (When Compiler Is Unavailable)
memo(Component)— skip re-rendering when props unchanged. Useful when: component re-renders often with same props,
re-rendering is expensive, parent re-renders for unrelated reasons. Useless when: props always differ, component is cheap, or it re-renders from its own state/context anyway.
useMemo(fn, deps)— cache computed values. Only for genuinely expensive work or preserving references passed to
memoized children.
useCallback(fn, deps)— cache function references. Use when passing callbacks to memoized children, in custom hooks
returning functions, or as Effect dependencies.
Server Components
- Server Components render on the server, send only output to client. No client JS.
- Can read databases, filesystems, APIs directly. Can be
asyncfunctions. - Cannot use
useState,useEffect, or any client-side React APIs. - Default (no directive needed). Client Components require
"use client"at file top. - Server Components can render Client Components as children. Client Components cannot import Server Components
directly.
"use server"marks Server Functions (Actions callable from client), not Server Components.- Automatic code-splitting: Client Component imports from Server Components are code-split automatically.
Streaming with Suspense
Start rendering immediately, stream slower parts as they resolve. Create promises in Server Components, pass to Client Components, read with use() inside ``.
Bundle Optimization
- Avoid bar
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: xobotyi
- Source: xobotyi/cc-foundry
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.