skills/frontend/tech-react/SKILL.md
React 19 patterns for components, hooks, Server Components, and data fetching. Use when writing React components, managing state with hooks, implementing Suspense boundaries, optimizing renders with proper memoization, or building Server/Client component hierarchies.
npx skillsauth add ravnhq/ai-toolkit tech-reactInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
React patterns evolve with each major version. React 19 introduced the use() hook for promise handling and formalized Server Component boundaries with clearer client/server semantics. Common pitfalls include:
React 19 improves these patterns: use() hook for consuming promises, Server Components for data fetching without extra requests, and useTransition() for non-blocking updates.
use() hook calls with Suspense boundaries for loading fallbackSee rules index for detailed patterns.
User: "Refactor this React component to reduce re-renders and clarify hook usage."
Expected behavior: Use tech-react guidance, follow its workflow, and return actionable output.
User: "I'm fetching data on the client with useEffect. How should I refactor this with Server Components?"
Expected behavior: Move data fetch to Server Component, pass promise to Client Component via use() hook, wrap with Suspense boundary.
User: "Write a Bash script to package release artifacts."
Expected behavior: Do not prioritize tech-react; choose a more relevant skill or proceed without it.
enabled option in data hooks to skip executionuse() suspendsuse()<Suspense> is a parent of the component, not a siblingkey={index} to key={item.id} with unique property from dataIncorrect:
function UserProfile({ userId }: { userId: string | null }) {
if (!userId) {
return <div>Select a user</div>;
}
// Hook called conditionally - React can't track it!
const [profile, setProfile] = useState(null);
return <div>{profile?.name}</div>;
}
Correct:
function UserProfile({ userId }: { userId: string | null }) {
const [profile, setProfile] = useState(null);
// Early return AFTER hooks
if (!userId) {
return <div>Select a user</div>;
}
return <div>{profile?.name}</div>;
}
Incorrect:
function Comments({ id }: { id: string }) {
const [comments, setComments] = useState([]);
useEffect(() => {
fetchComments(id).then(setComments);
}, [id]);
return <ul>{comments.map(c => <li key={c.id}>{c.text}</li>)}</ul>;
}
Correct:
function Comments({ commentsPromise }: { commentsPromise: Promise<Comment[]> }) {
const comments = use(commentsPromise);
return <ul>{comments.map(c => <li key={c.id}>{c.text}</li>)}</ul>;
}
function CommentsSection({ id }: { id: string }) {
return (
<Suspense fallback={<div>Loading comments...</div>}>
<Comments commentsPromise={fetchComments(id)} />
</Suspense>
);
}
Incorrect:
// BAD: Server Component with useState
async function NotesPage() {
const [selectedNote, setSelectedNote] = useState(null); // ERROR: Can't use state
const notes = await db.notes.getAll();
return (
<div>
{notes.map(note => (
<button onClick={() => setSelectedNote(note)}>
{note.title}
</button>
))}
</div>
);
}
Correct:
// Server Component - fetch data
async function NotesPage() {
const notes = await db.notes.getAll();
return (
<div>
<NotesList notes={notes} />
</div>
);
}
// Client Component - handle interaction
"use client";
function NotesList({ notes }: { notes: Note[] }) {
const [selectedNote, setSelectedNote] = useState<Note | null>(null);
return (
<div>
{notes.map(note => (
<button
key={note.id}
onClick={() => setSelectedNote(note)}
>
{note.title}
</button>
))}
</div>
);
}
testing
Transform user requests into detailed, precise prompts for AI models. Use when users say 'promptify', 'promptify this', 'rewrite this prompt', 'make this prompt better/more specific', or explicitly request prompt engineering or improvement of their request for better AI responses.
tools
Manage AI skills from the Ravn AI Toolkit via corvus CLI — install, update, remove, search, and configure skills for any project. Use when: (1) Installing AI skills into a project, (2) Updating installed skills to latest versions, (3) Browsing or searching available skills, (4) Configuring global or per-project skill sets, (5) Troubleshooting corvus setup. Triggers on: "install skills", "add skills", "update skills", "corvus", "skill manager", "browse skills", "set up AI rules".
development
Generate a gallery of design variations for a UI component. Takes an existing component (referenced by name, pasted code, or screenshot) and produces N distinct rendered alternatives in a single comparison page. Use when exploring visual directions, generating mockups, comparing design approaches for a component, creating A/B candidates, or when anyone says "show me options" or "give me variations" for a UI element.
tools
Create custom QA agent personalities for project-specific testing needs. Guided builder that asks about the specialty, tools, and test scenarios, then generates a personality file and registers it in the QA config. Trigger on "create a QA personality", "add a custom test agent", "build a webhook tester", or when the user needs a project-specific QA agent. Also triggered by /qa-create-personality.