| name | developing-with-react |
| description | React 18+ development with hooks, state management, component patterns, and Next.js integration. Use when building React applications or working with JSX/TSX components. Use when this capability is needed. |
| metadata | {"author":"fortiumpartners"} |
React Framework - Quick Reference
Version: 1.0.0 | Framework: React 18+ | Use Case: Fast lookups during active development
When to Use
Load this skill when:
package.json contains "react" dependency (>=18.0.0)
- Project has
.jsx or .tsx files in src/
- Next.js, Vite, or Create React App detected
- User mentions "React" in task description
Minimum Detection Confidence: 0.8 (80%)
Quick Start
import { FC, useState } from 'react';
interface Props {
title: string;
onAction?: () => void;
}
export const MyComponent: FC<Props> = ({ title, onAction }) => {
const [count, setCount] = useState(0);
return (
<div>
<h1>{title}</h1>
<p>Count: {count}</p>
<button onClick={() => setCount(c => c + 1)}>Increment</button>
<button onClick={onAction}>Action</button>
</div>
);
};
Component Design
Functional Component Structure
import { useState, useEffect } from 'react';
import type { FC, ReactNode } from 'react';
interface Props {
children: ReactNode;
className?: string;
}
export const Component: FC<Props> = ({ children, className }) => {
const [state, setState] = useState<string>('');
useEffect(() => {
}, []);
const handleClick = () => setState('clicked');
if (!children) return null;
return <div className={className}>{children}</div>;
};
Container/Presentational Pattern
export const UserProfileContainer: FC<{ userId: number }> = ({ userId }) => {
const [user, setUser] = useState<User | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch(`/api/users/${userId}`)
.then(res => res.json())
.then(setUser)
.finally(() => setLoading(false));
}, [userId]);
if (loading) return <LoadingSpinner />;
if (!user) return <ErrorMessage />;
return <UserProfile user={user} />;
};
export const UserProfile: FC<{ user: User }> = () => (
);
Core Hooks
useState - Local State
const [count, setCount] = useState(0);
const [user, setUser] = useState<User | null>(null);
setCount(prevCount => prevCount + 1);
const [data, setData] = useState(() => expensiveComputation());
setForm(prev => ({ ...prev, email: 'new@email.com' }));
useEffect - Side Effects
useEffect(() => {
fetchData();
}, []);
useEffect(() => {
fetchUser(userId);
}, [userId]);
useEffect(() => {
const subscription = api.subscribe();
return () => subscription.unsubscribe();
}, []);
useEffect(() => {
const controller = new AbortController();
fetch(url, { signal: controller.signal });
return () => controller.abort();
}, [url]);
useContext - Consume Context
interface ThemeContextType {
theme: 'light' | 'dark';
toggleTheme: () => void;
}
const ThemeContext = createContext<ThemeContextType | undefined>(undefined);
export const ThemeProvider: FC<{ children: ReactNode }> = ({ children }) => {
const [theme, setTheme] = useState<'light' | 'dark'>('light');
const toggleTheme = () => setTheme(prev => prev === 'light' ? 'dark' : 'light');
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
};
export const useTheme = () => {
const context = useContext(ThemeContext);
(!context) ();
context;
};
useReducer - Complex State
type Action = { type: 'increment' } | { type: 'decrement' } | { type: 'reset' };
const reducer = (state: number, action: Action): number => {
switch (action.type) {
case 'increment': return state + 1;
case 'decrement': return state - 1;
case 'reset': return 0;
default: return state;
}
};
const Counter = () => {
const [count, dispatch] = useReducer(reducer, 0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
);
};
Custom Hooks
function useFetch<T>(url: string) {
const [data, setData] = useState<T | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<Error | null>(null);
useEffect(() => {
const controller = new AbortController();
fetch(url, { signal: controller.signal })
.then(res => res.json())
.then(setData)
.catch(setError)
.finally(() => setLoading(false));
return () => controller.abort();
}, [url]);
return { data, loading, error };
}
const { data: user, loading, error } = useFetch<User>(`/api/users/${userId}`);
Performance Optimization
React.memo - Prevent Re-renders
export const ExpensiveComponent = memo(({ data }: { data: Data }) => {
return <div>{/* expensive rendering */}</div>;
});
export const CustomMemo = memo(
({ user }: { user: User }) => <div>{user.name}</div>,
(prev, next) => prev.user.id === next.user.id
);
useMemo & useCallback
const filteredItems = useMemo(() => {
return items.filter(item => item.includes(filter));
}, [items, filter]);
const handleClick = useCallback(() => {
setCount(c => c + 1);
}, []);
<MemoizedChild onClick={handleClick} />
Code Splitting
import { lazy, Suspense } from 'react';
const HeavyComponent = lazy(() => import('./HeavyComponent'));
const App = () => (
<Suspense fallback={<div>Loading...</div>}>
<HeavyComponent />
</Suspense>
);
Accessibility (WCAG 2.1 AA)
Essential Patterns
<button onClick={handleClick}>Click me</button> // Good
<div onClick={handleClick}>Click me</div> // Bad
<button aria-label="Close dialog">X</button>
<input type="email" aria-describedby="email-hint" />
<span id="email-hint">We'll never share your email</span>
<div aria-live="polite" aria-atomic="true">{statusMessage}</div>
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key === 'Escape') onClose();
if (e.key === 'Enter') onSubmit();
};
Form Accessibility
<form onSubmit={handleSubmit}>
<label htmlFor="email">Email</label>
<input
id="email"
type="email"
aria-invalid={!!errors.email}
aria-describedby={errors.email ? 'email-error' : undefined}
/>
{errors.email && <span id="email-error" role="alert">{errors.email}</span>}
</form>
TypeScript Quick Reference
Component Props
interface Props {
title: string;
subtitle?: string;
variant: 'primary' | 'secondary';
onClick?: () => void;
onSubmit: (data: FormData) => void;
children: ReactNode;
user: User;
}
export const Component: FC<Props> = ({ title, onClick }) => (
<div onClick={onClick}>{title}</div>
);
Event Handlers
const handleClick = (e: MouseEvent<HTMLButtonElement>) => {};
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {};
const handleSubmit = (e: FormEvent<HTMLFormElement>) => { e.preventDefault(); };
const handleKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {};
Refs
const inputRef = useRef<HTMLInputElement>(null);
useEffect(() => { inputRef.current?.focus(); }, []);
<input ref={inputRef} />
Anti-Patterns (Avoid These)
user.name = 'Jane'; setUser(user);
setUser({ ...user, name: 'Jane' });
{items.map((item, i) => <div key={i}>{item}</div>)}
{items.map(item => <div key={item.id}>{item}</div>)}
if (condition) { useState(0); }
useEffect(() => { fetchUser(userId); }, []);
useEffect(() => { fetchUser(userId); }, [userId]);
<Button onClick={() => handleClick(id)}>Click</Button>
Testing Quick Reference
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { axe, toHaveNoViolations } from 'jest-axe';
expect.extend(toHaveNoViolations);
describe('Button', () => {
it('renders with text', () => {
render(<Button>Click me</Button>);
expect(screen.getByRole('button', { name: /click me/i })).toBeInTheDocument();
});
it('handles click events', async () => {
const handleClick = jest.fn();
render(<Button onClick={handleClick}>Click</Button>);
await userEvent.click(screen.getByRole('button'));
expect(handleClick).toHaveBeenCalledTimes(1);
});
it('has no accessibility violations', async () => {
{ container } = ();
( (container)).();
});
});
Integration Checklist
When using this skill, ensure:
See Also
- REFERENCE.md - Comprehensive React guide with:
- Advanced component patterns (compound components, render props, HOCs)
- Complete hooks deep dive
- State management architectures (Context optimization, Redux, Zustand)
- Full WCAG 2.1 AA accessibility guide
- Performance profiling and optimization
- Testing strategies and patterns
- TypeScript advanced patterns
- Styling approaches (CSS Modules, styled-components, Tailwind)
- templates/ - Code generation templates
- examples/ - Real-world implementation examples
Version: 1.0.0 | Last Updated: 2025-01-01 | Status: Production Ready
Converted and distributed by TomeVault — claim your Tome and manage your conversions.