React 19 features including Server Components, Actions, and use() hook. Use when building modern React applications.
/plugin marketplace add IvanTorresEdge/molcajete.ai/plugin install ivantorresedge-react-tech-stacks-js-react@IvanTorresEdge/molcajete.aiThis skill inherits all available tools. When active, it can use any tool Claude has access to.
This skill covers React 19 features and patterns for building modern applications.
Use this skill when:
SERVER FIRST - Default to Server Components, use 'use client' only when needed for interactivity.
Server Components run on the server and send HTML to the client.
// app/users/page.tsx - Server Component (default)
import { getUsers } from '@/lib/api';
export default async function UsersPage(): Promise<React.ReactElement> {
const users = await getUsers();
return (
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
Client Components run in the browser for interactivity.
'use client';
import { useState } from 'react';
interface CounterProps {
initialValue?: number;
}
export function Counter({ initialValue = 0 }: CounterProps): React.ReactElement {
const [count, setCount] = useState(initialValue);
return (
<button type="button" onClick={() => setCount((c) => c + 1)}>
Count: {count}
</button>
);
}
Actions replace traditional form handlers with server-side processing.
// app/actions.ts
'use server';
import { revalidatePath } from 'next/cache';
import { redirect } from 'next/navigation';
export async function createUser(formData: FormData): Promise<void> {
const name = formData.get('name') as string;
const email = formData.get('email') as string;
await db.user.create({ data: { name, email } });
revalidatePath('/users');
redirect('/users');
}
// app/users/new/page.tsx
import { createUser } from '../actions';
export default function NewUserPage(): React.ReactElement {
return (
<form action={createUser}>
<input type="text" name="name" required />
<input type="email" name="email" required />
<button type="submit">Create User</button>
</form>
);
}
'use client';
import { useActionState } from 'react';
import { createUser } from '../actions';
interface FormState {
message: string;
success: boolean;
}
export function UserForm(): React.ReactElement {
const [state, formAction, isPending] = useActionState<FormState, FormData>(
createUser,
{ message: '', success: false }
);
return (
<form action={formAction}>
<input type="text" name="name" required disabled={isPending} />
<input type="email" name="email" required disabled={isPending} />
<button type="submit" disabled={isPending}>
{isPending ? 'Creating...' : 'Create User'}
</button>
{state.message && <p>{state.message}</p>}
</form>
);
}
The use() hook reads values from promises and contexts.
'use client';
import { use } from 'react';
interface User {
id: string;
name: string;
}
function UserProfile({ userPromise }: { userPromise: Promise<User> }): React.ReactElement {
const user = use(userPromise); // Suspends until resolved
return <h1>{user.name}</h1>;
}
// Usage with Suspense
function UserPage(): React.ReactElement {
const userPromise = fetchUser('123');
return (
<Suspense fallback={<div>Loading...</div>}>
<UserProfile userPromise={userPromise} />
</Suspense>
);
}
'use client';
import { use, createContext } from 'react';
const ThemeContext = createContext<'light' | 'dark'>('light');
function Button({ showIcon }: { showIcon: boolean }): React.ReactElement {
// Can use conditionally (unlike useContext)
if (showIcon) {
const theme = use(ThemeContext);
return <button className={theme}>With Icon</button>;
}
return <button>Without Icon</button>;
}
import { Suspense } from 'react';
export default function Dashboard(): React.ReactElement {
return (
<div>
<h1>Dashboard</h1>
<Suspense fallback={<UserSkeleton />}>
<UserInfo />
</Suspense>
<Suspense fallback={<StatsSkeleton />}>
<Stats />
</Suspense>
</div>
);
}
// app/page.tsx
import { Suspense } from 'react';
export default function Page(): React.ReactElement {
return (
<main>
{/* Renders immediately */}
<Header />
{/* Streams when ready */}
<Suspense fallback={<Loading />}>
<SlowComponent />
</Suspense>
{/* Renders immediately */}
<Footer />
</main>
);
}
// ServerWrapper.tsx (Server Component)
import { getData } from '@/lib/api';
import { InteractiveList } from './InteractiveList';
export async function ServerWrapper(): Promise<React.ReactElement> {
const data = await getData();
return <InteractiveList items={data} />;
}
// InteractiveList.tsx (Client Component)
'use client';
import { useState } from 'react';
interface InteractiveListProps {
items: Item[];
}
export function InteractiveList({ items }: InteractiveListProps): React.ReactElement {
const [selected, setSelected] = useState<string | null>(null);
return (
<ul>
{items.map((item) => (
<li
key={item.id}
onClick={() => setSelected(item.id)}
className={selected === item.id ? 'selected' : ''}
>
{item.name}
</li>
))}
</ul>
);
}
// ClientWrapper.tsx
'use client';
import { useState } from 'react';
interface ClientWrapperProps {
children: React.ReactNode;
}
export function ClientWrapper({ children }: ClientWrapperProps): React.ReactElement {
const [isOpen, setIsOpen] = useState(false);
return (
<div>
<button type="button" onClick={() => setIsOpen(!isOpen)}>
Toggle
</button>
{isOpen && children}
</div>
);
}
// Page.tsx (Server Component)
import { ClientWrapper } from './ClientWrapper';
import { ServerContent } from './ServerContent';
export default function Page(): React.ReactElement {
return (
<ClientWrapper>
<ServerContent /> {/* Server Component as child */}
</ClientWrapper>
);
}
| React 18 | React 19 |
|---|---|
| useEffect for data | async Server Component |
| useState + fetch | Server Action |
| Context.Consumer | use(Context) |
| Promise.then() | use(Promise) |
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.