tech-react
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.
Best use case
tech-react is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
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.
Teams using tech-react should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/tech-react/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How tech-react Compares
| Feature / Agent | tech-react | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
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.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Core Challenges
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:
- **Hook ordering violations**: Conditionally calling hooks breaks React's tracking system
- **Unnecessary memoization**: useMemo/useCallback/React.memo add overhead without measurement
- **Oversized components**: Mixing Server and Client logic prevents streaming optimization
- **Missing Suspense boundaries**: Async data without Suspense blocks entire render
- **Stale closures**: Effects with incorrect dependency arrays or missing cleanup
- **Key misuse**: Index keys cause state to attach to wrong list items after reorder
React 19 improves these patterns: `use()` hook for consuming promises, Server Components for data fetching without extra requests, and `useTransition()` for non-blocking updates.
## Workflow
1. **Identify component responsibilities**: Determine if component should be Server (data-heavy) or Client (interactive)
2. **Define hooks at top level**: All hooks must execute unconditionally before any returns
3. **Use Suspense for async**: Wrap `use()` hook calls with Suspense boundaries for loading fallback
4. **Compose with keys**: Use stable, unique keys for list items; use key prop to reset component state
5. **Measure before optimizing**: Profile with React DevTools before adding memoization
6. **Clean up subscriptions**: Always return cleanup function from effects that subscribe to systems
7. **Keep components small**: Extract Client Components for interactivity, let Server Components handle data
## Rules
See [rules index](rules/_sections.md) for detailed patterns.
## Examples
### Positive Trigger
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.
### Positive Trigger: Server Component Boundary
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.
### Non-Trigger
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.
## Troubleshooting
### Hook Call Violations ("Rendered more hooks than during the previous render")
- Error: React throws "Rendered fewer/more hooks than during the previous render"
- Cause: Hooks called inside conditions, loops, or early returns
- Solution: Move hook calls before any conditional logic; use `enabled` option in data hooks to skip execution
### Suspense Fallback Never Shows
- Error: Loading fallback doesn't appear when `use()` suspends
- Cause: Suspense boundary is not wrapping the component that calls `use()`
- Solution: Ensure `<Suspense>` is a parent of the component, not a sibling
### Server Component Can't Use State/Events
- Error: useState, onClick handlers don't work in Server Components
- Cause: Server Components render once on server; they can't respond to client interaction
- Solution: Extract interactive parts to Client Components with "use client" directive; Server Component handles data fetching and passes to Client Component
### useEffect Runs Twice or Creates Memory Leaks
- Error: Effect side effect runs multiple times; cleanup doesn't execute
- Cause: Missing dependency array or missing cleanup return function
- Solution: Include dependency array; return cleanup function for subscriptions/timers/listeners
### List Items Lose Focus or Appear in Wrong Order
- Error: Input focus jumps between rows; items appear shuffled after sort
- Cause: Using array index as key instead of stable unique identifier
- Solution: Change `key={index}` to `key={item.id}` with unique property from data
## Examples: Error Patterns
### Error 1: Conditional Hook
**Incorrect:**
```tsx
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:**
```tsx
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>;
}
```
### Error 2: Suspense Without use() Hook
**Incorrect:**
```tsx
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:**
```tsx
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>
);
}
```
### Error 3: Server/Client Boundary Confusion
**Incorrect:**
```tsx
// 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:**
```tsx
// 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>
);
}
```Related Skills
tech-drizzle
Drizzle ORM typesafe schema design, relational queries, prepared statements, migrations, and transactions. Use when working with Drizzle ORM, writing database queries, managing migrations, or optimizing query performance with prepared statements.
tech-android
Android and Kotlin development patterns — Compose, architecture, coroutines, Room, navigation, Hilt. Use when building Android apps, writing Jetpack Compose UI, or reviewing Android-specific code.
figma-to-react-components
Convert Figma component designs into production-ready React implementations with design token integration, accessibility via React Aria, and comprehensive documentation. Use when building React components from Figma designs, generating component implementation specs, or bridging design-to-development workflows.
agent-skills-manager
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".
type-system-audit
Audit a repository for type-system weaknesses using recent bug-fix commits as hard evidence. Produces prioritized findings tied to specific commits showing which types allowed real bugs. Use when: reviewing type safety, auditing types, analyzing type bugs. Triggers on: type audit, type system review, audit types, type safety audit.
ts-linter
Set up and enforce a strict, production-grade ESLint configuration for TypeScript projects, then systematically fix all linting issues. Use this skill whenever the user asks to add a linter or ESLint, enforce code quality rules, fix linting errors, clean up code style, or add type-aware linting. Trigger on: "lint", "eslint", "code quality", "static analysis", "strict linting", "make it stricter", "make the code stricter", "add better rules", "clean up the codebase", "enforce standards", "fix all the warnings", or "ShadCN lint errors". Handles detection, config generation, dependency installation, auto-fix, and manual remediation. Do NOT use for Biome or Rome projects, Prettier-only formatting, non-TypeScript/JavaScript projects, writing custom ESLint rules or plugins, husky/lint-staged/pre-commit hook setup, or when the user just wants to run an existing linter without changing its configuration.
transcript-notes
Convert meeting transcript .txt files into structured .md notes with metadata, TL;DR, key topics, action items, and quotes. Use when processing raw transcripts into formatted notes. Triggers on: "process transcript", "generate notes from transcript", "transcript to notes", "/transcript-notes".
test-plan-gen
Generate professional QA Test Plan documents (.docx or .pdf) from a structured interview. Trigger on "create/write a test plan", "I need a test plan", "prepare QA documentation", /testplan, or when a user uploads a PRD/requirements and wants a test plan generated.
test-case-gen
Generate, evaluate, audit, and normalize QA test cases to RAVN standards. Trigger on "generate/write/create test cases", "evaluate/score my test cases", "audit my test suite", "review test coverage", "normalize/reformat test cases", or when a user wants test design help. Also triggered by /testcases.
swift-concurrency
Swift Concurrency patterns — async/await, actors, tasks, Sendable conformance. Use when writing async/await code, implementing actors, working with structured concurrency, or ensuring data race safety.
rewrite-commit-history
Rewrite a feature branch's commit history into clean conventional commits that tell a progressive, linear story. Handles backup, soft reset, and atomic recommit. Use when: (1) Cleaning up messy WIP commits before PR, (2) Reorganizing commits into logical units, (3) Converting commits to conventional commit format. Triggers on: "rewrite history", "clean up commits", "rewrite commits", "conventional commits", "squash and rewrite", "reorganize commits".
qa-personality-builder
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.