hydraia
Use whenever the user asks to build, add, implement, or change a feature or functionality — or brings a user story or ticket to analyze, reports a bug or…
React 18/19 patterns including hooks discipline, server/client component boundaries, Suspense + error boundaries, form actions, data fetching, state management decision trees, and accessibility-first composition. Use when writing or reviewing React components.
$ npx -y skills add jdanigo/hydraia --skill react-patterns --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/react-patternsContext preview
The summary Claude sees to decide when to auto-load this skill.
React 18/19 patterns including hooks discipline, server/client component boundaries, Suspense + error boundaries, form actions, data fetching, state management decision trees, and accessibility-first composition. Use when writing or reviewing React components.
name: react-patterns description: React 18/19 patterns including hooks discipline, server/client component boundaries, Suspense + error boundaries, form actions, data fetching, state management decision trees, and accessibility-first composition. Use when writing or reviewing React components. metadata: origin: ECC
Idiomatic React 18/19 patterns for building robust, accessible, performant component trees.
// Good: derive during render
function Cart({ items }: { items: CartItem[] }) {
const total = items.reduce((sum, i) => sum + i.price * i.qty, 0);
return <span>{formatMoney(total)}</span>;
}
// Bad: derived state stored separately
function Cart({ items }: { items: CartItem[] }) {
const [total, setTotal] = useState(0);
useEffect(() => {
setTotal(items.reduce((sum, i) => sum + i.price * i.qty, 0));
}, [items]);
return <span>{formatMoney(total)}</span>;
}Derived state in `useEffect` adds a render cycle, can desync, and obscures the data flow.
Effects, mutations, network calls, and subscriptions live in event handlers or `useEffect` — never in the render body.
React has no inheritance model for components. Compose with `children`, render props, or component props.
See [rules/react/hooks.md](../../rules/react/hooks.md) for the full ruleset. Highlights:
Used by one component? -> useState inside it Used by parent + a few descendants? -> lift to nearest common ancestor Used across distant branches AND low-frequency reads (theme, auth, locale)? -> React Context High-frequency updates shared across the tree? -> external store (Zustand, Jotai, Redux Toolkit) Derived from a server? -> server-state library (TanStack Query, SWR, RSC fetch)
Most pages do not need context or a global store. Resist abstraction until duplicated lifting becomes painful.
// Server Component - default, async, never ships JS for itself
export default async function ProductPage({ params }: { params: { id: string } }) {
const product = await db.product.findUnique({ where: { id: params.id } });
if (!product) notFound();
return <ProductView product={product} />;
}
// Client Component - opt in with "use client"
"use client";
export function AddToCartButton({ productId }: { productId: string }) {
const [pending, startTransition] = useTransition();
return (
<button
disabled={pending}
onClick={() => startTransition(() => addToCart(productId))}
>
{pending ? "Adding..." : "Add to cart"}
</button>
);
}Boundaries:
<ErrorBoundary fallback={<ErrorView />}>
<Suspense fallback={<UserSkeleton />}>
<UserDetail id={id} />
</Suspense>
</ErrorBoundary>"use client";
import { useActionState } from "react";
const initial = { error: null as string | null };
async function updateUserAction(_prev: typeof initial, formData: FormData) {
"use server";
const parsed = UserSchema.safeParse(Object.fromEntries(formData));
if (!parsed.success) return { error: "Invalid input" };
await db.user.update({ where: { id: parsed.data.id }, data: parsed.data });
return { error: null };
}
export function UserForm() {
const [state, formAction, pending] = useActionState(updateUserAction, initial);
return (
<form action={formAction}>
<input name="name" required />
<button type="submit" disabled={pending}>Save</button>
{state.error && <p role="alert">{state.error}</p>}
</form>
);
}Use controlled when the value drives other UI, formats on every keystroke, or implements real-time validation.
For multi-step forms, dynamic field arrays, or cross-field validation: use a library (React Hook Form, TanStack Form). Roll-your-own state management for forms past trivial complexity is a maintenance trap.
| Need | Tool | |---|---| | Per-request data in Next.js App Router | RSC `await fetch()` | | Client-side cache + mutations + invalidation | TanStack Query | | Lightweight client cache + revalidation | SWR | | Real-time subscriptions | Server-Sent Events, WebSockets, or the lib's subscription API | | One-o
An agentic development harness for Claude Code. **One command runs the entire feature pipeline** — it collaborates with you on the design, then builds autonomously: plan, execute, double-review, and verify.
Repo: jdanigo/hydraia
Use whenever the user asks to build, add, implement, or change a feature or functionality — or brings a user story or ticket to analyze, reports a bug or…
Use when a design decision is made that is expensive to reverse, affects multiple components, or rejects a plausible alternative — record it as an Architecture…
Teaches the AI to design like a high-end agency. Defines the exact fonts, spacing, shadows, card structures, and animations that make a website feel expensive.…
Use when designing or reviewing an API surface — REST, GraphQL, or gRPC. Contract-first methodology: the contract artifact (OpenAPI 3.1, SDL, proto3) is…
Design banners for social media, ads, website heroes, creative assets, and print. Multiple art direction options with AI-generated visuals. Actions: design,…
You MUST use this before any creative work - creating features, building components, adding functionality, or modifying behavior. Explores user intent,…