بنقرة واحدة
react-patterns
React development patterns. Use when building React components, managing state, creating custom hooks, or optimizing React applications. Covers React 19 features, TypeScript integration, and composition patterns.
القائمة
React development patterns. Use when building React components, managing state, creating custom hooks, or optimizing React applications. Covers React 19 features, TypeScript integration, and composition patterns.
استنادا إلى تصنيف SOC المهني
Biome 2.x linting and formatting patterns. Use when configuring code quality tools, setting up linting rules, formatting code, or integrating with CI/CD. Covers migration from ESLint/Prettier.
Hono 4.x web framework patterns. Use when building APIs, middleware, routing, or server-side applications. Covers multi-runtime support (Node, Bun, Cloudflare Workers), validation, CORS, and error handling.
Radix UI primitive patterns. Use when building accessible, unstyled UI components like dialogs, dropdowns, tooltips, tabs, and selects. Covers Tailwind styling, keyboard navigation, animations, and portal management.
Tailwind CSS 4.x utility-first styling patterns. Use when building UI components, creating responsive layouts, implementing design systems, or customizing themes. Covers CSS-first configuration, @theme directive, and component patterns.
Vite 7.x build tool patterns. Use when configuring build setup, development server, environment variables, asset handling, or optimizing production builds for React applications.
Plan infrastructure capacity for expected load. Use when sizing systems, planning for growth, or analyzing resource requirements. Covers load estimation and resource sizing.
| name | react-patterns |
| description | React development patterns. Use when building React components, managing state, creating custom hooks, or optimizing React applications. Covers React 19 features, TypeScript integration, and composition patterns. |
Platform: Web and Mobile (shared React patterns). For React Native-specific patterns (Pressable, ScrollView, FlashList, safe areas), see the react-native-patterns skill.
Patterns for building maintainable React applications with TypeScript, leveraging React 19 features and composition patterns.
API Reference: Use Context7 MCP for full React API reference (
mcp__context7__resolve-library-id→react).
// Shares implicit state between parent and children
const TabsContext = createContext<{ activeTab: string; setActiveTab: (id: string) => void } | null>(null);
function Tabs({ children, defaultTab }: { children: ReactNode; defaultTab: string }) {
const [activeTab, setActiveTab] = useState(defaultTab);
return <TabsContext.Provider value={{ activeTab, setActiveTab }}>{children}</TabsContext.Provider>;
}
function Tab({ id, children }: { id: string; children: ReactNode }) {
const ctx = use(TabsContext);
if (!ctx) throw new Error('Tab must be used within Tabs');
return (
<button role="tab" aria-selected={ctx.activeTab === id} onClick={() => ctx.setActiveTab(id)}>
{children}
</button>
);
}
// Named slots for flexible composition
interface CardProps { header?: ReactNode; footer?: ReactNode; children: ReactNode; }
function Card({ header, footer, children }: CardProps) {
return (
<div className="card">
{header && <div className="card-header">{header}</div>}
<div className="card-body">{children}</div>
{footer && <div className="card-footer">{footer}</div>}
</div>
);
}
// Unwrap promises and context — simpler than useContext
function UserProfile({ userPromise }: { userPromise: Promise<User> }) {
const user = use(userPromise); // Suspends until resolved
return <div>{user.name}</div>;
}
async function updateUser(prevState: { error?: string }, formData: FormData) {
'use server';
return { error: undefined };
}
function UserForm() {
const [state, formAction, isPending] = useActionState(updateUser, {});
return (
<form action={formAction}>
<input name="name" disabled={isPending} />
{state.error && <p className="error">{state.error}</p>}
<button disabled={isPending}>{isPending ? 'Saving...' : 'Save'}</button>
</form>
);
}
function TodoList({ todos }: { todos: Todo[] }) {
const [optimisticTodos, addOptimisticTodo] = useOptimistic(
todos,
(state, newTodo: Todo) => [...state, newTodo]
);
async function handleAdd(formData: FormData) {
const todo = { id: crypto.randomUUID(), text: formData.get('text') as string };
addOptimisticTodo(todo);
await saveTodo(todo);
}
return (
<form action={handleAdd}>
{optimisticTodos.map(todo => <li key={todo.id}>{todo.text}</li>)}
<input name="text" /><button>Add</button>
</form>
);
}
// Object return for multiple named values
function useAuth() {
const [user, setUser] = useState<User | null>(null);
const [loading, setLoading] = useState(true);
const login = async (credentials: Credentials) => { setUser(await api.login(credentials)); };
return { user, loading, login };
}
// Tuple return for positional access (like useState)
function useToggle(initial = false): [boolean, () => void] {
const [value, setValue] = useState(initial);
return [value, useCallback(() => setValue(v => !v), [])];
}
// Composing hooks
function useLocalStorage<T>(key: string, initial: T) {
const [value, setValue] = useState<T>(() => {
const stored = localStorage.getItem(key);
return stored ? JSON.parse(stored) : initial;
});
useEffect(() => { localStorage.setItem(key, JSON.stringify(value)); }, [key, value]);
return [value, setValue] as const;
}
// Extend HTML element props
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
variant?: 'primary' | 'secondary';
loading?: boolean;
}
function Button({ variant = 'primary', loading, children, ...props }: ButtonProps) {
return <button className={variant} disabled={loading} {...props}>{loading ? 'Loading...' : children}</button>;
}
// Generic components with full type inference
interface ListProps<T> { items: T[]; renderItem: (item: T) => ReactNode; keyExtractor: (item: T) => string; }
function List<T>({ items, renderItem, keyExtractor }: ListProps<T>) {
return <ul>{items.map(item => <li key={keyExtractor(item)}>{renderItem(item)}</li>)}</ul>;
}
// Refs as props (React 19+) — forwardRef is deprecated
interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
label: string;
ref?: React.Ref<HTMLInputElement>;
}
function Input({ label, ref, ...props }: InputProps) {
return <label>{label}<input ref={ref} {...props} /></label>;
}
type Action =
| { type: 'FETCH_START' }
| { type: 'FETCH_SUCCESS'; payload: User[] }
| { type: 'FETCH_ERROR'; payload: string };
function reducer(state: { data: User[]; loading: boolean; error: string | null }, action: Action) {
switch (action.type) {
case 'FETCH_START': return { ...state, loading: true, error: null };
case 'FETCH_SUCCESS': return { ...state, loading: false, data: action.payload };
case 'FETCH_ERROR': return { ...state, loading: false, error: action.payload };
}
}
// memo + useCallback prevent unnecessary re-renders
const ListItem = memo(function ListItem({ item, onDelete }: ItemProps) {
return <li>{item.name}<button onClick={() => onDelete(item.id)}>Delete</button></li>;
});
function List() {
const [items, setItems] = useState<Item[]>([]);
const handleDelete = useCallback((id: string) => {
setItems(items => items.filter(item => item.id !== id));
}, []);
return <>{items.map(item => <ListItem key={item.id} item={item} onDelete={handleDelete} />)}</>;
}
// Lazy loading with Suspense
const Dashboard = lazy(() => import('./Dashboard'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<Routes><Route path="/dashboard" element={<Dashboard />} /></Routes>
</Suspense>
);
}
class ErrorBoundary extends Component<{ children: ReactNode; fallback?: ReactNode }, { hasError: boolean }> {
state = { hasError: false };
static getDerivedStateFromError(): { hasError: boolean } { return { hasError: true }; }
componentDidCatch(error: Error, info: ErrorInfo) { console.error(error, info); }
render() {
return this.state.hasError ? (this.props.fallback ?? <div>Something went wrong</div>) : this.props.children;
}
}
// Wrap async data loading with Suspense
function UserProfile({ userId }: { userId: string }) {
const user = use(fetchUser(userId)); // Suspends
return <div>{user.name}</div>;
}