Agent skill
react-typescript
Build modern React applications with TypeScript. Covers React 18+ patterns, hooks, component architecture, state management (Zustand, Redux Toolkit), server components, and best practices. Use for React development, TypeScript integration, component design, and frontend architecture.
Stars
163
Forks
31
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/data/react-typescript
SKILL.md
React with TypeScript
Build production-ready React applications using TypeScript with modern patterns and best practices.
Instructions
- Always use TypeScript - Define proper types for props, state, and API responses
- Prefer functional components - Use hooks over class components
- Follow component composition - Build small, reusable, single-responsibility components
- Implement proper error boundaries - Wrap critical UI sections
- Use React 18+ features - Concurrent features, Suspense, transitions when appropriate
Component Patterns
Basic Component Structure
tsx
import { useState, useCallback } from 'react';
interface ButtonProps {
label: string;
onClick: () => void;
variant?: 'primary' | 'secondary' | 'danger';
disabled?: boolean;
loading?: boolean;
}
export function Button({
label,
onClick,
variant = 'primary',
disabled = false,
loading = false,
}: ButtonProps) {
const handleClick = useCallback(() => {
if (!disabled && !loading) {
onClick();
}
}, [disabled, loading, onClick]);
return (
<button
type="button"
onClick={handleClick}
disabled={disabled || loading}
className={`btn btn-${variant}`}
aria-busy={loading}
>
{loading ? <Spinner /> : label}
</button>
);
}
Custom Hooks Pattern
tsx
import { useState, useEffect, useCallback } from 'react';
interface UseApiResult<T> {
data: T | null;
loading: boolean;
error: Error | null;
refetch: () => void;
}
function useApi<T>(url: string): UseApiResult<T> {
const [data, setData] = useState<T | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<Error | null>(null);
const fetchData = useCallback(async () => {
setLoading(true);
setError(null);
try {
const response = await fetch(url);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const json = await response.json();
setData(json);
} catch (err) {
setError(err instanceof Error ? err : new Error('Unknown error'));
} finally {
setLoading(false);
}
}, [url]);
useEffect(() => {
fetchData();
}, [fetchData]);
return { data, loading, error, refetch: fetchData };
}
Compound Component Pattern
tsx
import { createContext, useContext, useState, ReactNode } from 'react';
interface AccordionContextType {
openItems: Set<string>;
toggle: (id: string) => void;
}
const AccordionContext = createContext<AccordionContextType | null>(null);
function useAccordion() {
const context = useContext(AccordionContext);
if (!context) throw new Error('Must be used within Accordion');
return context;
}
interface AccordionProps {
children: ReactNode;
allowMultiple?: boolean;
}
export function Accordion({ children, allowMultiple = false }: AccordionProps) {
const [openItems, setOpenItems] = useState<Set<string>>(new Set());
const toggle = (id: string) => {
setOpenItems(prev => {
const next = new Set(allowMultiple ? prev : []);
if (prev.has(id)) {
next.delete(id);
} else {
next.add(id);
}
return next;
});
};
return (
<AccordionContext.Provider value={{ openItems, toggle }}>
<div role="region">{children}</div>
</AccordionContext.Provider>
);
}
Accordion.Item = function AccordionItem({ id, title, children }: {
id: string;
title: string;
children: ReactNode;
}) {
const { openItems, toggle } = useAccordion();
const isOpen = openItems.has(id);
return (
<div>
<button
onClick={() => toggle(id)}
aria-expanded={isOpen}
aria-controls={`panel-${id}`}
>
{title}
</button>
{isOpen && <div id={`panel-${id}`}>{children}</div>}
</div>
);
};
State Management
Zustand (Recommended for most cases)
tsx
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
interface UserState {
user: User | null;
isAuthenticated: boolean;
login: (user: User) => void;
logout: () => void;
}
export const useUserStore = create<UserState>()(
persist(
(set) => ({
user: null,
isAuthenticated: false,
login: (user) => set({ user, isAuthenticated: true }),
logout: () => set({ user: null, isAuthenticated: false }),
}),
{ name: 'user-storage' }
)
);
React Query for Server State
tsx
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
function useTodos() {
return useQuery({
queryKey: ['todos'],
queryFn: () => fetch('/api/todos').then(r => r.json()),
staleTime: 5 * 60 * 1000, // 5 minutes
});
}
function useAddTodo() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (newTodo: Todo) =>
fetch('/api/todos', {
method: 'POST',
body: JSON.stringify(newTodo),
}),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['todos'] });
},
});
}
Project Structure
src/
├── components/
│ ├── ui/ # Reusable UI components
│ ├── features/ # Feature-specific components
│ └── layouts/ # Layout components
├── hooks/ # Custom hooks
├── stores/ # State management
├── services/ # API services
├── types/ # TypeScript types
├── utils/ # Utility functions
└── pages/ # Page components (if not using router)
Best Practices
- Type everything - No
anytypes, useunknownif needed - Memoize appropriately - Use
useMemo,useCallback,React.memofor expensive operations - Handle loading/error states - Every async operation needs these states
- Use proper keys - Never use array index as key for dynamic lists
- Avoid prop drilling - Use context or state management for deep prop passing
- Code split - Use
React.lazy()for route-level code splitting - Test components - Write unit tests with React Testing Library
When to Use
- Building React applications with TypeScript
- Creating reusable component libraries
- Implementing complex state management
- Setting up new React projects
- Refactoring class components to functional
Notes
- Requires React 18+ for latest features
- Use Vite for new projects (faster than CRA)
- Consider Next.js for SSR/SSG requirements
- Always include proper accessibility attributes
Didn't find tool you were looking for?