C

Comprehensive React Module

Streamline your workflow with this skill, should, used, building. Includes structured workflows, validation checks, and reusable patterns for development.

SkillClipticsdevelopmentv1.0.0MIT
0 views0 copies

Comprehensive React Module

A complete development skill for building modern React applications with hooks, context, suspense, server components, and performance optimization patterns. Covers the full spectrum from component architecture through state management to deployment-ready production patterns.

When to Use This Skill

Choose this skill when:

  • Building new React applications from scratch with modern best practices
  • Migrating class-based components to functional components with hooks
  • Implementing complex state management across deeply nested component trees
  • Setting up code splitting, lazy loading, and suspense boundaries
  • Optimizing render performance with memoization and profiling

Consider alternatives when:

  • Working exclusively with Next.js routing and SSR → use a Next.js-specific skill
  • Building React Native mobile applications → use a React Native skill
  • Need only UI component patterns → use a React UI patterns skill
  • Working with a specific state library like Redux or Zustand → use that library's skill

Quick Start

# Create a new React project with Vite npm create vite@latest my-app -- --template react-ts cd my-app && npm install
// src/App.tsx — Modern React application shell import { Suspense, lazy } from 'react'; import { ErrorBoundary } from './components/ErrorBoundary'; import { ThemeProvider } from './contexts/ThemeContext'; import { AuthProvider } from './contexts/AuthContext'; const Dashboard = lazy(() => import('./pages/Dashboard')); const Settings = lazy(() => import('./pages/Settings')); export default function App() { return ( <ErrorBoundary fallback={<p>Something went wrong</p>}> <ThemeProvider> <AuthProvider> <Suspense fallback={<LoadingSkeleton />}> <Router /> </Suspense> </AuthProvider> </ThemeProvider> </ErrorBoundary> ); }

Core Concepts

Component Architecture Patterns

PatternPurposeExample
Container/PresentationalSeparate logic from UIUserContainerUserCard
Compound ComponentsShared implicit state<Select><Option /></Select>
Render PropsFlexible rendering delegation<DataFetcher render={data => ...} />
Custom HooksReusable stateful logicuseDebounce, useLocalStorage
Higher-Order ComponentsCross-cutting concernswithAuth(ProtectedPage)

Custom Hook Patterns

// Reusable data fetching hook with caching function useFetch<T>(url: string, options?: RequestInit) { const [state, setState] = useState<{ data: T | null; loading: boolean; error: Error | null; }>({ data: null, loading: true, error: null }); useEffect(() => { const controller = new AbortController(); setState(prev => ({ ...prev, loading: true })); fetch(url, { ...options, signal: controller.signal }) .then(res => { if (!res.ok) throw new Error(`HTTP ${res.status}`); return res.json(); }) .then(data => setState({ data, loading: false, error: null })) .catch(error => { if (error.name !== 'AbortError') { setState({ data: null, loading: false, error }); } }); return () => controller.abort(); }, [url]); return state; }

Context with Reducer Pattern

// Scalable state management without external libraries type Action = | { type: 'SET_USER'; payload: User } | { type: 'LOGOUT' } | { type: 'SET_THEME'; payload: 'light' | 'dark' }; function appReducer(state: AppState, action: Action): AppState { switch (action.type) { case 'SET_USER': return { ...state, user: action.payload, isAuthenticated: true }; case 'LOGOUT': return { ...state, user: null, isAuthenticated: false }; case 'SET_THEME': return { ...state, theme: action.payload }; default: return state; } } const AppContext = createContext<{ state: AppState; dispatch: React.Dispatch<Action>; } | null>(null); export function useApp() { const context = useContext(AppContext); if (!context) throw new Error('useApp must be inside AppProvider'); return context; }

Configuration

ParameterTypeDefaultDescription
strictModebooleantrueEnable React StrictMode double-rendering in dev
suspenseFallbackReactNode<Spinner />Default loading component for Suspense boundaries
errorBoundaryFallbackReactNode<ErrorPage />Default error fallback component
codeSplitThresholdstring'route'Split at route, component, or feature level
memoizationStrategystring'selective'Memoize all, selective, or none
contextSplittingbooleantrueSplit contexts to prevent unnecessary re-renders

Best Practices

  1. Split contexts by update frequency — Keep authentication context separate from theme context. Components subscribing to one won't re-render when the other changes. Group state that changes together.

  2. Use useCallback and useMemo intentionally — Only memoize values passed as props to memoized children or used in dependency arrays. Premature memoization adds complexity without measurable benefit.

  3. Colocate state with its consumers — Start with local state and lift only when siblings need it. Reach for context when prop drilling exceeds 2-3 levels. External stores suit cross-cutting global state.

  4. Implement error boundaries at feature boundaries — A failing widget shouldn't crash the entire page. Place error boundaries around independent features so failures remain isolated.

  5. Prefer composition over configuration — Build flexible components through children and slots rather than increasingly complex prop APIs. Compound components scale better than components with 20+ props.

Common Issues

Infinite re-render loops with useEffect — This happens when objects or arrays in the dependency array are recreated each render. Stabilize references with useMemo, extract values to primitives, or move object creation inside the effect. Never omit dependencies to "fix" the loop.

Stale closures in event handlers and timers — Callbacks inside useEffect or setTimeout capture the state value from when they were created. Use refs for values that need to be current inside long-lived closures, or use the functional form of setState (setCount(prev => prev + 1)).

Context causing unnecessary re-renders — When a context provider's value is an object literal created inline, every render creates a new reference and all consumers re-render. Memoize the context value with useMemo and split contexts so consumers only subscribe to the state slices they need.

Community

Reviews

Write a review

No reviews yet. Be the first to review this template!

Similar Templates