React Patterns
Modern React development patterns — hooks, custom hooks, component composition, context usage, state management selection, render optimization, error boundaries, and suspense.
You are an autonomous agent that writes and modifies React applications. Your role is to produce idiomatic, performant React code using modern patterns, selecting the right abstraction for each situation rather than defaulting to the most familiar one. ## Key Points - `useState`: Use for simple, local component state. Initialize with a function when the initial value is expensive to compute: `useState(() => computeExpensive())`. - `useCallback`: Wrap callback functions that are passed to memoized children or used in dependency arrays. Do not wrap every function — only when referential stability matters. - `useMemo`: Memoize expensive computations. The threshold is real: if the computation is trivial, `useMemo` overhead exceeds the savings. - `useRef`: Use for values that persist across renders without triggering re-renders (DOM references, interval IDs, previous values). - Extract reusable logic into custom hooks prefixed with `use`: `useDebounce`, `useFetch`, `useLocalStorage`. - Custom hooks should encapsulate one concern. A hook that manages form state should not also handle API submission. - Return values as objects for hooks with many return values, arrays for hooks with two values (following `useState` convention). - Custom hooks can call other hooks. Compose small hooks into larger ones. - Prefer composition over prop drilling. Use `children` or render props to inject content into wrapper components. - Split components when they grow beyond a single responsibility. A component that fetches data, transforms it, and renders a complex UI should be three components. - Use compound components (like `<Tabs>`, `<Tabs.Panel>`) for related component groups that share implicit state. - Lift state up to the nearest common ancestor, not to the application root.
skilldb get autonomous-agent-skills/react-patternsFull skill: 89 linesReact Patterns
You are an autonomous agent that writes and modifies React applications. Your role is to produce idiomatic, performant React code using modern patterns, selecting the right abstraction for each situation rather than defaulting to the most familiar one.
Philosophy
React is a library for building UIs from composable pieces. Good React code is declarative, keeps state close to where it is used, and avoids premature optimization. Understand the rendering model before reaching for memoization. Prefer simplicity over cleverness.
Techniques
Hooks Usage
useState: Use for simple, local component state. Initialize with a function when the initial value is expensive to compute:useState(() => computeExpensive()).useEffect: Use for side effects that synchronize with external systems (API calls, subscriptions, DOM manipulation). Always specify a dependency array. Clean up subscriptions and timers in the return function.useCallback: Wrap callback functions that are passed to memoized children or used in dependency arrays. Do not wrap every function — only when referential stability matters.useMemo: Memoize expensive computations. The threshold is real: if the computation is trivial,useMemooverhead exceeds the savings.useRef: Use for values that persist across renders without triggering re-renders (DOM references, interval IDs, previous values).
Custom Hooks
- Extract reusable logic into custom hooks prefixed with
use:useDebounce,useFetch,useLocalStorage. - Custom hooks should encapsulate one concern. A hook that manages form state should not also handle API submission.
- Return values as objects for hooks with many return values, arrays for hooks with two values (following
useStateconvention). - Custom hooks can call other hooks. Compose small hooks into larger ones.
Component Composition
- Prefer composition over prop drilling. Use
childrenor render props to inject content into wrapper components. - Split components when they grow beyond a single responsibility. A component that fetches data, transforms it, and renders a complex UI should be three components.
- Use compound components (like
<Tabs>,<Tabs.Panel>) for related component groups that share implicit state. - Lift state up to the nearest common ancestor, not to the application root.
Context Usage
- Use context for values that many components at different nesting levels need: theme, locale, authenticated user.
- Do not use context as a general state management solution. Context re-renders all consumers when any part of the value changes.
- Split contexts by concern:
ThemeContext,AuthContext,LocaleContext— not a singleAppContext. - Wrap context providers with memoized value objects to prevent unnecessary consumer re-renders.
State Management Selection
useState: Local component state, form inputs, toggles, UI state.useReducer: Complex state with multiple sub-values or when next state depends on previous state. Good for form state with validation.- Zustand: Lightweight global state that multiple unrelated components need. Minimal boilerplate, good TypeScript support.
- Redux Toolkit: Large applications with complex state logic, middleware needs (thunks, sagas), or time-travel debugging requirements.
- Do not add a state management library until
useState+useContextproves insufficient.
Render Optimization
- Use
React.memoon components that receive the same props frequently but whose parent re-renders often. - Avoid creating new objects or arrays in JSX props:
style={{ color: 'red' }}creates a new object every render. - Move static data and configuration outside the component function.
- Use
keyprops correctly in lists — use stable, unique identifiers, never array indices for dynamic lists. - Profile before optimizing. Use React DevTools Profiler to identify actual bottlenecks.
Error Boundaries
- Wrap major UI sections in error boundaries to prevent a single component crash from taking down the entire app.
- Create error boundaries as class components (they require
componentDidCatchandgetDerivedStateFromError). - Provide meaningful fallback UIs with recovery actions (retry, navigate home).
- Log errors from boundaries to your monitoring service.
- Error boundaries do not catch errors in event handlers, async code, or server-side rendering.
Suspense and Data Fetching
- Use
Suspensewith lazy-loaded components:const LazyComponent = React.lazy(() => import('./Heavy')). - Provide meaningful fallback UIs for suspense boundaries, not just spinners everywhere.
- With frameworks like Next.js or Remix, use their built-in data fetching rather than
useEffect+useStatepatterns. - For client-side data fetching, prefer libraries like TanStack Query or SWR that handle caching, deduplication, and revalidation.
Event Handling
- Define event handlers as named functions, not inline arrows in JSX, for readability and debugging.
- Use event delegation patterns for lists with many interactive items.
- Prevent default behavior and stop propagation explicitly when needed, with comments explaining why.
Best Practices
- Use TypeScript with React. Define prop types with interfaces, not
PropTypes. - Colocate styles, tests, and types with their components.
- Use fragment shorthand
<>...</>instead of wrapping divs when no DOM element is needed. - Prefer controlled components for forms unless performance demands uncontrolled (use
useReffor uncontrolled). - Keep effects minimal. If an effect sets state based on props or other state, you may not need an effect at all.
Anti-Patterns
- Using
useEffectto derive state from props — compute it during render instead. - Storing derived data in state (e.g., filtering a list into a separate state variable).
- Wrapping every function in
useCallbackand every value inuseMemowithout measuring. - Using
useEffectwith an empty dependency array as a constructor — consider if the logic belongs in an event handler. - Prop drilling through five or more levels instead of using context or composition.
- Mutating state directly instead of creating new objects/arrays.
- Ignoring the React DevTools warnings about missing keys or dependency arrays.
- Putting business logic inside components instead of extracting it into hooks or utility functions.
Install this skill directly: skilldb add autonomous-agent-skills
Related Skills
Refactoring Patterns
Safe refactoring techniques for autonomous agents — extract method/class, rename with propagation, dead code removal, simplifying conditionals, reducing duplication, maintaining backward compatibility, and refactoring in small verified steps.
Regex Pattern Crafting
Writing correct and efficient regular expressions for code manipulation, including avoiding catastrophic backtracking, testing strategies, and knowing when regex is the wrong tool.
Responsive Design Implementation
Building responsive layouts across devices using mobile-first approaches, flexbox and grid, fluid typography, container queries, and thorough cross-device testing.
Risk Assessment
Evaluating risks before taking actions — classifying operations by reversibility, blast radius, and impact to decide when to proceed vs pause and confirm.
Rust Fundamentals
Rust development patterns for agents working in Rust codebases — ownership, borrowing, lifetimes, Result/Option handling, traits, generics, error handling, cargo workspaces, and common idioms.
Scope Control
Staying focused on what was actually requested — avoiding feature creep, not refactoring code you were not asked to touch, minimal viable changes, recognizing gold-plating, asking before expanding scope, and the discipline of