Skip to main content
ClaudeWave
Skill2k estrellas del repoactualizado 3mo ago

react-dev

The react-dev skill provides type-safe patterns for building React components with TypeScript across React 18-19. It covers generic component typing, proper event handler and ref typing, React 19 breaking changes like ref-as-prop and useActionState, custom hooks, and router integration with TanStack Router or React Router. Use this skill when implementing typed React components, handling forms and events, migrating to React 19, or structuring reusable component libraries with compile-time type guarantees.

Instalar en Claude Code
Copiar
git clone --depth 1 https://github.com/softaworks/agent-toolkit /tmp/react-dev && cp -r /tmp/react-dev/dist/plugins/react-dev/skills/react-dev ~/.claude/skills/react-dev
Después abre una sesión nueva de Claude Code; el skill carga automáticamente.

SKILL.md

# React TypeScript

Type-safe React = compile-time guarantees = confident refactoring.

<when_to_use>

- Building typed React components
- Implementing generic components
- Typing event handlers, forms, refs
- Using React 19 features (Actions, Server Components, use())
- Router integration (TanStack Router, React Router)
- Custom hooks with proper typing

NOT for: non-React TypeScript, vanilla JS React

</when_to_use>

<react_19_changes>

React 19 breaking changes require migration. Key patterns:

**ref as prop** - forwardRef deprecated:

```typescript
// React 19 - ref as regular prop
type ButtonProps = {
  ref?: React.Ref<HTMLButtonElement>;
} & React.ComponentPropsWithoutRef<'button'>;

function Button({ ref, children, ...props }: ButtonProps) {
  return <button ref={ref} {...props}>{children}</button>;
}
```

**useActionState** - replaces useFormState:

```typescript
import { useActionState } from 'react';

type FormState = { errors?: string[]; success?: boolean };

function Form() {
  const [state, formAction, isPending] = useActionState(submitAction, {});
  return <form action={formAction}>...</form>;
}
```

**use()** - unwraps promises/context:

```typescript
function UserProfile({ userPromise }: { userPromise: Promise<User> }) {
  const user = use(userPromise); // Suspends until resolved
  return <div>{user.name}</div>;
}
```

See [react-19-patterns.md](references/react-19-patterns.md) for useOptimistic, useTransition, migration checklist.

</react_19_changes>

<component_patterns>

**Props** - extend native elements:

```typescript
type ButtonProps = {
  variant: 'primary' | 'secondary';
} & React.ComponentPropsWithoutRef<'button'>;

function Button({ variant, children, ...props }: ButtonProps) {
  return <button className={variant} {...props}>{children}</button>;
}
```

**Children typing**:

```typescript
type Props = {
  children: React.ReactNode;          // Anything renderable
  icon: React.ReactElement;           // Single element
  render: (data: T) => React.ReactNode;  // Render prop
};
```

**Discriminated unions** for variant props:

```typescript
type ButtonProps =
  | { variant: 'link'; href: string }
  | { variant: 'button'; onClick: () => void };

function Button(props: ButtonProps) {
  if (props.variant === 'link') {
    return <a href={props.href}>Link</a>;
  }
  return <button onClick={props.onClick}>Button</button>;
}
```

</component_patterns>

<event_handlers>

Use specific event types for accurate target typing:

```typescript
// Mouse
function handleClick(e: React.MouseEvent<HTMLButtonElement>) {
  e.currentTarget.disabled = true;
}

// Form
function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
  e.preventDefault();
  const formData = new FormData(e.currentTarget);
}

// Input
function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
  console.log(e.target.value);
}

// Keyboard
function handleKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {
  if (e.key === 'Enter') e.currentTarget.blur();
}
```

See [event-handlers.md](references/event-handlers.md) for focus, drag, clipboard, touch, wheel events.

</event_handlers>

<hooks_typing>

**useState** - explicit for unions/null:

```typescript
const [user, setUser] = useState<User | null>(null);
const [status, setStatus] = useState<'idle' | 'loading'>('idle');
```

**useRef** - null for DOM, value for mutable:

```typescript
const inputRef = useRef<HTMLInputElement>(null);  // DOM - use ?.
const countRef = useRef<number>(0);               // Mutable - direct access
```

**useReducer** - discriminated unions for actions:

```typescript
type Action =
  | { type: 'increment' }
  | { type: 'set'; payload: number };

function reducer(state: State, action: Action): State {
  switch (action.type) {
    case 'set': return { ...state, count: action.payload };
    default: return state;
  }
}
```

**Custom hooks** - tuple returns with as const:

```typescript
function useToggle(initial = false) {
  const [value, setValue] = useState(initial);
  const toggle = () => setValue(v => !v);
  return [value, toggle] as const;
}
```

**useContext** - null guard pattern:

```typescript
const UserContext = createContext<User | null>(null);

function useUser() {
  const user = useContext(UserContext);
  if (!user) throw new Error('useUser outside UserProvider');
  return user;
}
```

See [hooks.md](references/hooks.md) for useCallback, useMemo, useImperativeHandle, useSyncExternalStore.

</hooks_typing>

<generic_components>

Generic components infer types from props - no manual annotations at call site.

**Pattern** - keyof T for column keys, render props for custom rendering:

```typescript
type Column<T> = {
  key: keyof T;
  header: string;
  render?: (value: T[keyof T], item: T) => React.ReactNode;
};

type TableProps<T> = {
  data: T[];
  columns: Column<T>[];
  keyExtractor: (item: T) => string | number;
};

function Table<T>({ data, columns, keyExtractor }: TableProps<T>) {
  return (
    <table>
      <thead>
        <tr>{columns.map(col => <th key={String(col.key)}>{col.header}</th>)}</tr>
      </thead>
      <tbody>
        {data.map(item => (
          <tr key={keyExtractor(item)}>
            {columns.map(col => (
              <td key={String(col.key)}>
                {col.render ? col.render(item[col.key], item) : String(item[col.key])}
              </td>
            ))}
          </tr>
        ))}
      </tbody>
    </table>
  );
}
```

**Constrained generics** for required properties:

```typescript
type HasId = { id: string | number };

function List<T extends HasId>({ items }: { items: T[] }) {
  return <ul>{items.map(item => <li key={item.id}>...</li>)}</ul>;
}
```

See [generic-components.md](examples/generic-components.md) for Select, List, Modal, FormField patterns.

</generic_components>

<server_components>

React 19 Server Components run on server, can be async.

**Async data fetching**:

```typescript
export default async function UserPage({ params }: { params: { id: string } }) {
  const
commandsSkill

Add a skill to the project with validation and README generation

sync-skills-readmeSlash Command

Sync root README.md with current skills inventory from skills/ directory

ascii-ui-mockup-generatorSubagent

Use this agent when you need to visualize UI concepts through ASCII mockups before implementation. Examples: <example>Context: User has an idea for a dashboard layout with data tables and charts. user: 'I want to create a dashboard that shows user analytics with a sidebar navigation, main content area with charts, and a data table below' assistant: 'I'll use the ascii-ui-mockup-generator agent to create multiple ASCII mockup variations for your dashboard concept.' <commentary>The user wants to visualize a UI concept, so use the ascii-ui-mockup-generator to create multiple ASCII representations they can choose from.</commentary></example> <example>Context: User is designing a form layout with multiple input fields. user: 'I need a contact form with name, email, message fields and a submit button' assistant: 'Let me use the ascii-ui-mockup-generator to create several ASCII mockup options for your contact form layout.' <commentary>Since the user needs to visualize form layouts, use the ascii-ui-mockup-generator to provide multiple ASCII design options.</commentary></example>

codebase-pattern-finderSubagent

codebase-pattern-finder is a useful subagent_type for finding similar implementations, usage examples, or existing patterns that can be modeled after. It will give you concrete code examples based on what you're looking for! It's sorta like codebase-locator, but it will not only tell you the location of files, it will also give you code details!

communication-excellence-coachSubagent

PROACTIVELY use when reviewing communication drafts or preparing difficult conversations. Provides email refinement, tone calibration, roleplay practice, and presentation feedback with actionable suggestions.

general-purposeSubagent

Default agent for handling complex, multi-step tasks with automatic delegation capabilities

mermaid-diagram-specialistSubagent

Mermaid diagram specialist for creating flowcharts, sequence diagrams, ERDs,

ui-ux-designerSubagent

Expert UI/UX design critic and advisor who provides research-backed, opinionated feedback on interfaces. Use when you need honest assessment of design decisions, want to avoid generic "AI slop" aesthetics, need evidence-based UX guidance, or want distinctive design direction grounded in actual user behavior research. This agent will push back on bad ideas and cite sources for every recommendation.