react-19 — Claude Code skill: React 19 patterns, how to install
Skill for React 19 with React Compiler: no manual memoization, server components first, ref as a prop.
npx skills add prowler-cloud/prowler --skill react-19 -a claude-codeWhat react-19 does
The skill teaches the agent to write components following React 19 and React Compiler rules. React Compiler optimizes code automatically, so useMemo and useCallback are no longer needed — the agent writes plain functions and variables, the compiler memoizes everything. Server components are now the default, the "use client" directive only where state hooks, event handlers, or browser APIs are required.
Includes the new use() hook for reading promises and conditional context, useActionState for forms with pending state, and ref as a regular prop without forwardRef. The agent imports hooks by name (import { useState } from "react"), not through React.useState.
Triggers when writing .tsx components. If the project uses Next.js App Router or Server Actions, the nextjs-16 skill is recommended alongside.
What it helps with
- remove unnecessary
useMemoanduseCallbackfrom React 19 components - split server and client components following new rules
- rewrite
forwardReftorefas a prop - handle promises with the
use()hook instead ofuseEffect - set up forms with
useActionStateand pending indicators
Example prompts for the agent
- write a list component in React 19 without memoization
- convert this component from `forwardRef` to `ref` as a prop
- create a server component for the page, client component only for the button
How to install react-19
1Skills CLI (Vercel)
npx skills add prowler-cloud/prowler --skill react-19 -a claude-code2Manually: put the files in place
~/.claude/skills/react-19/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/react-19/
1Skills CLI (Vercel)
npx skills add prowler-cloud/prowler --skill react-19 -a codex2Manually: put the files in place
.agents/skills/react-19/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add prowler-cloud/prowler --skill react-19 -a cursor2Manually: put the files in place
.cursor/skills/react-19/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install prowler-cloud/prowler react-192Manually: put the files in place
.github/skills/react-19/SKILL.md1Skills CLI (Vercel)
npx skills add prowler-cloud/prowler --skill react-19 -a gemini-cli2Platform CLI
gemini skills install https://github.com/prowler-cloud/prowler --path skills/react-19Manually: put the files in place
.devin/skills/react-19/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add prowler-cloud/prowler --skill react-19 -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
From the same set4
The whole set →Similar
Questions about react-19
How to install react-19 in Claude Code?
Run npx skills add prowler-cloud/prowler --skill react-19 -a claude-code, the skill will appear in ~/.claude/skills/react-19/SKILL.md.
What does the react-19 skill do?
Teaches the agent to write components following React 19 rules: no manual memoization (React Compiler optimizes automatically), server components first, ref as a regular prop, the use() hook for promises, and useActionState for forms.
When is the "use client" directive needed?
Only where state hooks (useState, useEffect, useRef, useContext), event handlers, or browser APIs like window and localStorage are used. Server components work without the directive.
Source text
SKILL.md · Apache-2.0
---
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-16.
license: Apache-2.0
metadata:
author: prowler-cloud
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)
```typescript
// ✅ 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)
```typescript
// ✅ ALWAYS: Named imports
import { useState, useEffect, useRef } from "react";
// ❌ NEVER
import React from "react";
import * as React from "react";
```
## Server Components First
```typescript
// ✅ 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
```typescript
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
```typescript
"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)
```typescript
// ✅ 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} />);
```
© prowler-cloud · Apache-2.0 · prowler-cloud/prowler