Our review
Provides patterns for React 19 components using the React Compiler, covering automatic memoization, server components, the use() hook, actions, and ref as prop.
Strengths
- Eliminates manual memoization with React Compiler.
- Promotes server components as default.
- Introduces new hooks like use() and useActionState for simpler async handling.
- Simplifies ref passing without forwardRef.
Limitations
- Requires React 19 and React Compiler setup.
- Not backward compatible with older React versions.
- Some patterns like use() are still experimental in some environments.
Use when building new React 19 applications or migrating existing codebases that can adopt React Compiler.
Avoid when working with projects that cannot upgrade to React 19 or do not have React Compiler enabled.
Security analysis
SafeThe skill provides React 19 coding patterns and best practices. It does not instruct execution of any commands, tools, or actions that could harm systems or exfiltrate data. The allowed-tools list is standard but the skill itself only recommends code patterns, not system-level operations.
No concerns found
Examples
Rewrite this React component to follow React 19 patterns: remove all useMemo and useCallback calls, use named imports, and ensure it's a server component if possible.Update this form component to use the new useActionState hook from React 19 for managing submission state.Remove the forwardRef wrapper from this component and pass ref directly as a prop instead, as per React 19.name: react-19 description: > React 19 patterns with React Compiler. Trigger: When writing React 19 components/hooks in .tsx (React Compiler rules, hook patterns, refs as props). If using Next.js App Router/Server Actions, also use nextjs-15. license: Apache-2.0 metadata: author: Alan version: "1.0" scope: [root, ui] auto_invoke: "Writing React components" allowed-tools: Read, Edit, Write, Glob, Grep, Bash, WebFetch, WebSearch, Task
No Manual Memoization (REQUIRED)
// ✅ React Compiler handles optimization automatically
function Component({ items }) {
const filtered = items.filter(x => x.active);
const sorted = filtered.sort((a, b) => a.name.localeCompare(b.name));
const handleClick = (id) => {
console.log(id);
};
return <List items={sorted} onClick={handleClick} />;
}
// ❌ NEVER: Manual memoization
const filtered = useMemo(() => items.filter(x => x.active), [items]);
const handleClick = useCallback((id) => console.log(id), []);
Imports (REQUIRED)
// ✅ ALWAYS: Named imports
import { useState, useEffect, useRef } from "react";
// ❌ NEVER
import React from "react";
import * as React from "react";
Server Components First
// ✅ Server Component (default) - no directive
export default async function Page() {
const data = await fetchData();
return <ClientComponent data={data} />;
}
// ✅ Client Component - only when needed
"use client";
export function Interactive() {
const [state, setState] = useState(false);
return <button onClick={() => setState(!state)}>Toggle</button>;
}
When to use "use client"
- useState, useEffect, useRef, useContext
- Event handlers (onClick, onChange)
- Browser APIs (window, localStorage)
use() Hook
import { use } from "react";
// Read promises (suspends until resolved)
function Comments({ promise }) {
const comments = use(promise);
return comments.map(c => <div key={c.id}>{c.text}</div>);
}
// Conditional context (not possible with useContext!)
function Theme({ showTheme }) {
if (showTheme) {
const theme = use(ThemeContext);
return <div style={{ color: theme.primary }}>Themed</div>;
}
return <div>Plain</div>;
}
Actions & useActionState
"use server";
async function submitForm(formData: FormData) {
await saveToDatabase(formData);
revalidatePath("/");
}
// With pending state
import { useActionState } from "react";
function Form() {
const [state, action, isPending] = useActionState(submitForm, null);
return (
<form action={action}>
<button disabled={isPending}>
{isPending ? "Saving..." : "Save"}
</button>
</form>
);
}
ref as Prop (No forwardRef)
// ✅ React 19: ref is just a prop
function Input({ ref, ...props }) {
return <input ref={ref} {...props} />;
}
// ❌ Old way (unnecessary now)
const Input = forwardRef((props, ref) => <input ref={ref} {...props} />);
Next.js App Router Expert
Development
A skill that turns Claude into a Next.js App Router expert.
README Generator
Development
Creates professional and comprehensive README.md files for your projects.
API Documentation Writer
Development
Generates comprehensive API documentation in OpenAPI/Swagger format.