Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
blencorp avatar

React

  • 50 installs
  • 101 repo stars
  • Updated November 28, 2025
  • blencorp/claude-code-kit

React is a Claude Code skill that provides core React 19 patterns for hooks, Suspense, lazy loading, and TypeScript component structure.

About

React is a skill that gives Claude core React 19 patterns for hooks, Suspense, lazy loading, component structure, and TypeScript best practices. A developer uses it when creating React components, using hooks, implementing code splitting, or working with Suspense boundaries. It documents React 19 breaking changes such as ref-as-prop replacing forwardRef.

  • React 19 hooks, component-structure, and TypeScript patterns
  • Lazy loading and code splitting with React.lazy and Suspense
  • Documents React 19 changes: ref as a prop, no forwardRef, no React.FC

React by the numbers

  • 50 all-time installs (skills.sh)
  • Ranked #1,306 of 2,245 Frontend Development skills by installs in the Skillselion catalog
  • Data as of Aug 4, 2026 (Skillselion catalog sync)
At a glance

react capabilities & compatibility

Capabilities
frontend · ui design · component patterns
Use cases
frontend · ui design
IDEs
vscode · cursor ide
From the docs

What react says it does

Core React 19 patterns including hooks, Suspense, lazy loading, component structure, TypeScript best practices, and performance optimization.
SKILL.md
Essential React 19 patterns for building modern applications with hooks, Suspense, lazy loading, and TypeScript.
SKILL.md
`forwardRef` no longer needed - pass `ref` as a prop directly
SKILL.md
npx skills add https://github.com/blencorp/claude-code-kit --skill react

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs50
repo stars101
Last updatedNovember 28, 2025
Repositoryblencorp/claude-code-kit

What it does

Build React 19 components with hooks, Suspense, lazy loading, and typed props.

Who is it for?

Writing React 19 components and hooks with TypeScript

Skip if: Non-React frameworks or backend work

When should I use this skill?

Working with React components, hooks, lazy loading, or Suspense boundaries

What you get

Components follow React 19 conventions with correct hooks, memoization, and Suspense usage.

  • React components
  • Custom hooks
  • Lazy-loaded modules

By the numbers

  • 9-item React component checklist

Files

SKILL.mdMarkdownGitHub ↗

React Core Patterns

Purpose

Essential React 19 patterns for building modern applications with hooks, Suspense, lazy loading, and TypeScript.

Note: React 19 (released December 2024) breaking changes:

  • forwardRef no longer needed - pass ref as a prop directly
  • propTypes removed (silently ignored)
  • New JSX transform required
  • React.FC type discouraged - use direct function components instead

When to Use This Skill

  • Creating React components
  • Using React hooks (useState, useEffect, useCallback, useMemo)
  • Implementing lazy loading and code splitting
  • Working with Suspense boundaries
  • React-specific TypeScript patterns
  • Performance optimization with React

---

Quick Start

Component Structure Template

import { useState, useCallback } from 'react';

interface Props {
  userId: string;
  onUpdate?: (data: UserData) => void;
}

interface UserData {
  name: string;
  email: string;
}

function UserProfile({ userId, onUpdate }: Props) {
  const [data, setData] = useState<UserData | null>(null);

  const handleUpdate = useCallback((newData: UserData) => {
    setData(newData);
    onUpdate?.(newData);
  }, [onUpdate]);

  return (
    <div>
      {/* Component content */}
    </div>
  );
}

export default UserProfile;

Component Checklist

Creating a React component? Follow this:

  • [ ] Use function components with typed props (not React.FC)
  • [ ] Define interfaces for Props and local state
  • [ ] Use useCallback for event handlers passed to children
  • [ ] Use useMemo for expensive computations
  • [ ] Lazy load if heavy component: lazy(() => import())
  • [ ] Wrap lazy components in <Suspense> with fallback
  • [ ] Default export at bottom
  • [ ] No conditional hooks (hooks must be called in same order)
  • [ ] Pass ref as a prop (no forwardRef needed in React 19)

---

Core Hooks Patterns

useState

// Simple state
const [count, setCount] = useState<number>(0);

// Object state
const [user, setUser] = useState<User | null>(null);

// Array state
const [items, setItems] = useState<Item[]>([]);

// Functional updates when depending on previous state
setCount(prev => prev + 1);
setItems(prev => [...prev, newItem]);

useCallback

// Wrap functions passed to child components
const handleClick = useCallback((id: string) => {
  console.log('Clicked:', id);
}, []); // Empty deps if no dependencies

// With dependencies
const handleUpdate = useCallback((data: FormData) => {
  apiCall(userId, data);
}, [userId]); // Re-create when userId changes

useMemo

// Expensive computation
const sortedItems = useMemo(() => {
  return items.sort((a, b) => a.score - b.score);
}, [items]);

// Derived state
const totalPrice = useMemo(() => {
  return cart.reduce((sum, item) => sum + item.price, 0);
}, [cart]);

useEffect

// Run once on mount
useEffect(() => {
  fetchData();
}, []);

// Run when dependency changes
useEffect(() => {
  if (userId) {
    loadUserData(userId);
  }
}, [userId]);

// Cleanup
useEffect(() => {
  const subscription = subscribe(userId);
  return () => subscription.unsubscribe();
}, [userId]);

---

Lazy Loading & Code Splitting

Basic Lazy Loading

import React, { Suspense } from 'react';

// Lazy load heavy component
const HeavyChart = React.lazy(() => import('./HeavyChart'));

function Dashboard() {
  return (
    <div>
      <h1>Dashboard</h1>
      <Suspense fallback={<div>Loading chart...</div>}>
        <HeavyChart />
      </Suspense>
    </div>
  );
}

Multiple Lazy Components

const AdminPanel = React.lazy(() => import('./AdminPanel'));
const UserSettings = React.lazy(() => import('./UserSettings'));
const Reports = React.lazy(() => import('./Reports'));

function App() {
  return (
    <Suspense fallback={<LoadingSpinner />}>
      <Routes>
        <Route path="/admin" element={<AdminPanel />} />
        <Route path="/settings" element={<UserSettings />} />
        <Route path="/reports" element={<Reports />} />
      </Routes>
    </Suspense>
  );
}

Feature-Based Code Splitting

// features/auth/index.tsx
export { default } from './AuthFeature';

// Lazy load entire feature
const AuthFeature = React.lazy(() => import('~/features/auth'));

<Suspense fallback={<FeatureLoader />}>
  <AuthFeature />
</Suspense>

---

Suspense Patterns

Suspense Boundaries

// Wrap data-fetching components
<Suspense fallback={<Skeleton />}>
  <UserProfile userId={id} />
</Suspense>

// Nested Suspense for granular loading
<Suspense fallback={<PageLoader />}>
  <Header />
  <Suspense fallback={<ContentSkeleton />}>
    <MainContent />
  </Suspense>
  <Footer />
</Suspense>

Error Boundaries with Suspense

import { ErrorBoundary } from 'react-error-boundary';

<ErrorBoundary fallback={<ErrorFallback />}>
  <Suspense fallback={<Loading />}>
    <DataComponent />
  </Suspense>
</ErrorBoundary>

---

TypeScript Patterns

Component Props

// Basic props
interface ButtonProps {
  label: string;
  onClick: () => void;
  disabled?: boolean;
}

// Props with children
interface CardProps {
  title: string;
  children: React.ReactNode;
}

// Props with specific child types
interface ListProps {
  children: React.ReactElement<ItemProps> | React.ReactElement<ItemProps>[];
}

// Props with event handlers
interface FormProps {
  onSubmit: (data: FormData) => void;
  onChange?: (field: string, value: unknown) => void;
}

Hooks TypeScript

// useState with type
const [user, setUser] = useState<User | null>(null);
const [items, setItems] = useState<Item[]>([]);

// useRef with type
const inputRef = useRef<HTMLInputElement>(null);
const timerRef = useRef<number | null>(null);

// Custom hook with return type
function useUser(id: string): { user: User | null; loading: boolean } {
  const [user, setUser] = useState<User | null>(null);
  const [loading, setLoading] = useState(true);

  // ... implementation

  return { user, loading };
}

---

Performance Optimization

React.memo

// Memoize component to prevent unnecessary re-renders
const UserCard = React.memo<UserCardProps>(({ user, onUpdate }) => {
  return (
    <div>
      <h3>{user.name}</h3>
      <button onClick={() => onUpdate(user.id)}>Update</button>
    </div>
  );
});

// Custom comparison function
const UserCard = React.memo(UserCardComponent, (prevProps, nextProps) => {
  return prevProps.user.id === nextProps.user.id;
});

Avoiding Re-renders

// ❌ Bad: Creates new function on every render
function Parent() {
  return <Child onClick={() => console.log('clicked')} />;
}

// ✅ Good: Stable function reference
function Parent() {
  const handleClick = useCallback(() => {
    console.log('clicked');
  }, []);

  return <Child onClick={handleClick} />;
}

---

Common Patterns

Conditional Rendering

// Ternary operator
{isLoading ? <Spinner /> : <Content />}

// Logical AND
{error && <ErrorMessage error={error} />}

// Nullish coalescing
{user ?? <GuestView />}

// Early return for loading states
function Component() {
  const { data } = useSomeHook();

  // ❌ Avoid early returns for loading - breaks hooks rules
  // Use Suspense instead

  return <div>{data.map(...)}</div>;
}

Lists and Keys

// Always use stable keys
{items.map(item => (
  <ItemCard key={item.id} item={item} />
))}

// Never use index as key if list can reorder
// ❌ Bad
{items.map((item, index) => (
  <ItemCard key={index} item={item} />
))}

---

File Organization

Feature-Based Structure

src/
├── features/
│   ├── auth/
│   │   ├── components/
│   │   ├── hooks/
│   │   ├── types/
│   │   └── index.tsx
│   └── posts/
│       ├── components/
│       ├── hooks/
│       ├── types/
│       └── index.tsx
├── components/  # Shared components
├── hooks/       # Shared hooks
└── types/       # Shared types

Component Co-location

features/posts/
├── components/
│   ├── PostCard.tsx
│   ├── PostList.tsx
│   └── PostForm.tsx
├── hooks/
│   ├── usePost.ts
│   └── usePosts.ts
├── types/
│   └── post.ts
└── index.tsx  # Public API

---

Common Mistakes to Avoid

1. Conditional Hooks

// ❌ Never do this
function Component({ condition }) {
  if (condition) {
    const [state, setState] = useState(0); // Breaks rules of hooks
  }
}

// ✅ Do this
function Component({ condition }) {
  const [state, setState] = useState(0);
  // Use state conditionally, not the hook
}

2. Missing Dependencies

// ❌ Bad: Missing dependency
useEffect(() => {
  fetchUser(userId);
}, []); // userId should be in deps

// ✅ Good: All dependencies listed
useEffect(() => {
  fetchUser(userId);
}, [userId]);

3. Mutating State

// ❌ Bad: Mutating state directly
const handleAdd = () => {
  items.push(newItem); // Don't mutate
  setItems(items);
};

// ✅ Good: Create new array
const handleAdd = () => {
  setItems([...items, newItem]);
};

---

Additional Resources

For more detailed patterns, see:

  • component-patterns.md - Advanced component patterns
  • performance.md - Performance optimization techniques
  • typescript-patterns.md - TypeScript best practices
  • hooks-patterns.md - Custom hooks and advanced patterns

Related skills

FAQ

Which React version does this cover?

React 19, released December 2024, including its breaking changes.

Is forwardRef still needed?

No, in React 19 you pass ref as a prop directly instead of using forwardRef.

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.