Advanced React Patterns and Real-World Projects
Master advanced React patterns and build production-ready applications.
Advanced React Patterns: Taking Your Skills to the Next Level
Advanced React patterns help you write more flexible, reusable, and maintainable code. These patterns are commonly used by professional React developers.
Key Advanced Patterns
Compound Components Components that work together, sharing state implicitly. Like LEGO blocks designed to fit together perfectly.
Custom Hooks Extract component logic into reusable functions. Create your own tools that you can use in any component.
State Machines Model complex component states and transitions. Perfect for multi-step forms or complex UI flows.
When to Use Advanced Patterns
- Building reusable component libraries
- Managing complex state logic
- Sharing behavior between components
- Creating flexible, extensible APIs
1// Compound Components Pattern2import React, { createContext, useContext, useState } from 'react';34const SelectContext = createContext();56function Select({ children, defaultValue, onChange }) {7 const [value, setValue] = useState(defaultValue);8 const [isOpen, setIsOpen] = useState(false);910 const updateValue = (newValue) => {11 setValue(newValue);12 setIsOpen(false);13 onChange?.(newValue);14 };1516 return (17 <SelectContext.Provider value={{ value, isOpen, setIsOpen, updateValue }}>18 <div className="select-container">19 {children}20 </div>21 </SelectContext.Provider>22 );23}2425Select.Trigger = function SelectTrigger() {26 const { value, isOpen, setIsOpen } = useContext(SelectContext);2728 return (29 <button onClick={() => setIsOpen(!isOpen)}>30 {value || 'Select an option'}31 <span>{isOpen ? '▲' : '▼'}</span>32 </button>33 );34};3536Select.Options = function SelectOptions({ children }) {37 const { isOpen } = useContext(SelectContext);3839 if (!isOpen) return null;4041 return <div className="select-options">{children}</div>;42};4344Select.Option = function SelectOption({ value, children }) {45 const { value: selectedValue, updateValue } = useContext(SelectContext);4647 return (48 <div49 className={selectedValue === value ? 'selected' : ''}50 onClick={() => updateValue(value)}51 >52 {children}53 </div>54 );55};5657// Usage58function App() {59 return (60 <Select defaultValue="react" onChange={(val) => console.log('Selected:', val)}>61 <Select.Trigger />62 <Select.Options>63 <Select.Option value="react">React</Select.Option>64 <Select.Option value="vue">Vue</Select.Option>65 </Select.Options>66 </Select>67 );68}6970// Custom Hooks7172// useLocalStorage - Sync state with localStorage73function useLocalStorage(key, initialValue) {74 const [storedValue, setStoredValue] = useState(() => {75 try {76 const item = window.localStorage.getItem(key);77 return item ? JSON.parse(item) : initialValue;78 } catch (error) {79 return initialValue;80 }81 });8283 const setValue = (value) => {84 try {85 setStoredValue(value);86 window.localStorage.setItem(key, JSON.stringify(value));87 } catch (error) {88 console.error('Error saving to localStorage:', error);89 }90 };9192 return [storedValue, setValue];93}9495// useDebounce - Delay updates96function useDebounce(value, delay) {97 const [debouncedValue, setDebouncedValue] = useState(value);9899 useEffect(() => {100 const timer = setTimeout(() => {101 setDebouncedValue(value);102 }, delay);103104 return () => clearTimeout(timer);105 }, [value, delay]);106107 return debouncedValue;108}109110// Usage example111function SearchComponent() {112 const [searchTerm, setSearchTerm] = useState('');113 const debouncedSearch = useDebounce(searchTerm, 500);114 const [savedSearches, setSavedSearches] = useLocalStorage('searches', []);115116 useEffect(() => {117 if (debouncedSearch) {118 console.log('Searching for:', debouncedSearch);119 }120 }, [debouncedSearch]);121122 return (123 <div>124 <input125 value={searchTerm}126 onChange={(e) => setSearchTerm(e.target.value)}127 placeholder="Search..."128 />129 <p>Debounced: {debouncedSearch}</p>130 <p>Saved searches: {savedSearches.length}</p>131 </div>132 );133}134135// 🚦 STATE MACHINES WITH useReducer136137// Complex form with multiple steps138const formMachine = {139 initial: 'editing',140 states: {141 editing: {142 on: {143 SUBMIT: 'validating'144 }145 },146 validating: {147 on: {148 VALID: 'submitting',149 INVALID: 'editing'150 }151 },152 submitting: {153 on: {154 SUCCESS: 'success',155 ERROR: 'error'156 }157 },158 success: {159 on: {160 RESET: 'editing'161 }162 },163 error: {164 on: {165 RETRY: 'submitting',166 RESET: 'editing'167 }168 }169 }170};171172function formReducer(state, action) {173 const nextState = formMachine.states[state.status]?.on?.[action.type];174175 if (!nextState) {176 return state;177 }178179 return {180 ...state,181 status: nextState,182 ...action.payload183 };184}185186function MultiStepForm() {187 const [state, dispatch] = useReducer(formReducer, {188 status: formMachine.initial,189 data: {},190 errors: {}191 });192193 const handleSubmit = async (formData) => {194 dispatch({ type: 'SUBMIT' });195196 // Validate197 const errors = validateForm(formData);198 if (Object.keys(errors).length > 0) {199 dispatch({ type: 'INVALID', payload: { errors } });200 return;201 }202203 dispatch({ type: 'VALID' });204205 try {206 await submitForm(formData);207 dispatch({ type: 'SUCCESS' });208 } catch (error) {209 dispatch({ type: 'ERROR', payload: { error: error.message } });210 }211 };212213 return (214 <div className="form-container">215 {state.status === 'editing' && (216 <form onSubmit={(e) => {217 e.preventDefault();218 handleSubmit(new FormData(e.target));219 }}>220 {/* Form fields */}221 <button type="submit">Submit</button>222 </form>223 )}224225 {state.status === 'validating' && <div>Validating...</div>}226 {state.status === 'submitting' && <div>Submitting...</div>}227 {state.status === 'success' && (228 <div>229 Success!230 <button onClick={() => dispatch({ type: 'RESET' })}>231 Submit Another232 </button>233 </div>234 )}235 {state.status === 'error' && (236 <div>237 Error: {state.error}238 <button onClick={() => dispatch({ type: 'RETRY' })}>Retry</button>239 <button onClick={() => dispatch({ type: 'RESET' })}>Reset</button>240 </div>241 )}242 </div>243 );244}
Building a Real-World Project: Task Management App
Let's build a complete task management application that demonstrates how to combine various React concepts into a cohesive, production-ready application.
Project Features
- Task CRUD operations
- Categories and search
- Dark mode toggle
- Local storage persistence
Architecture
- State Management: Context API + useReducer
- Data Persistence: LocalStorage
- Component Structure: Feature-based organization
Learning Goals
- Apply React best practices
- Handle complex state management
- Implement real-world features
- Write maintainable code
1// Simple Task Management App2import React, { createContext, useContext, useReducer, useEffect, useState } from 'react';34const AppContext = createContext();56const initialState = {7 user: null,8 tasks: [],9 categories: ['Work', 'Personal', 'Shopping', 'Health'],10 filter: {11 category: 'all',12 completed: 'all',13 search: ''14 },15 theme: 'light'16};1718function appReducer(state, action) {19 switch (action.type) {20 case 'SET_USER':21 return { ...state, user: action.payload };2223 case 'ADD_TASK':24 return {25 ...state,26 tasks: [...state.tasks, action.payload]27 };2829 case 'UPDATE_TASK':30 return {31 ...state,32 tasks: state.tasks.map(task =>33 task.id === action.payload.id ? action.payload : task34 )35 };3637 case 'DELETE_TASK':38 return {39 ...state,40 tasks: state.tasks.filter(task => task.id !== action.payload)41 };4243 case 'TOGGLE_TASK':44 return {45 ...state,46 tasks: state.tasks.map(task =>47 task.id === action.payload48 ? { ...task, completed: !task.completed, updatedAt: new Date() }49 : task50 )51 };5253 case 'SET_FILTER':54 return {55 ...state,56 filter: { ...state.filter, ...action.payload }57 };5859 case 'TOGGLE_THEME':60 return {61 ...state,62 theme: state.theme === 'light' ? 'dark' : 'light'63 };6465 case 'REORDER_TASKS':66 return {67 ...state,68 tasks: action.payload69 };7071 default:72 return state;73 }74}7576// 3. MAIN APP PROVIDER77function AppProvider({ children }) {78 const [state, dispatch] = useReducer(appReducer, initialState, (initial) => {79 // Load from localStorage80 const saved = localStorage.getItem('taskapp_state');81 return saved ? { ...initial, ...JSON.parse(saved) } : initial;82 });8384 // Persist to localStorage85 useEffect(() => {86 localStorage.setItem('taskapp_state', JSON.stringify(state));87 }, [state]);8889 // Apply theme90 useEffect(() => {91 document.documentElement.setAttribute('data-theme', state.theme);92 }, [state.theme]);9394 return (95 <AppContext.Provider value={{ state, dispatch }}>96 {children}97 </AppContext.Provider>98 );99}100101// 4. CUSTOM HOOKS102function useApp() {103 const context = useContext(AppContext);104 if (!context) {105 throw new Error('useApp must be used within AppProvider');106 }107 return context;108}109110function useTasks() {111 const { state } = useApp();112 const { tasks, filter } = state;113114 // Filter tasks based on current filter115 return tasks.filter(task => {116 if (filter.category !== 'all' && task.category !== filter.category) {117 return false;118 }119120 if (filter.completed === 'active' && task.completed) {121 return false;122 }123124 if (filter.completed === 'completed' && !task.completed) {125 return false;126 }127128 if (filter.search && !task.title.toLowerCase().includes(filter.search.toLowerCase())) {129 return false;130 }131132 return true;133 });134}135136// 5. MAIN COMPONENTS137function TaskForm({ onClose }) {138 const { state, dispatch } = useApp();139 const [formData, setFormData] = useState({140 title: '',141 description: '',142 priority: 'medium',143 category: state.categories[0],144 tags: [],145 dueDate: ''146 });147148 const handleSubmit = (e) => {149 e.preventDefault();150151 const newTask = {152 ...formData,153 id: Date.now().toString(),154 completed: false,155 createdAt: new Date(),156 updatedAt: new Date(),157 dueDate: formData.dueDate ? new Date(formData.dueDate) : undefined158 };159160 dispatch({ type: 'ADD_TASK', payload: newTask });161 onClose();162 };163164 return (165 <form onSubmit={handleSubmit} className="task-form">166 <h2>Add New Task</h2>167168 <input169 type="text"170 placeholder="Task title"171 value={formData.title}172 onChange={(e) => setFormData({ ...formData, title: e.target.value })}173 required174 />175176 <textarea177 placeholder="Description (optional)"178 value={formData.description}179 onChange={(e) => setFormData({ ...formData, description: e.target.value })}180 />181182 <select183 value={formData.priority}184 onChange={(e) => setFormData({ ...formData, priority: e.target.value })}185 >186 <option value="low">Low Priority</option>187 <option value="medium">Medium Priority</option>188 <option value="high">High Priority</option>189 </select>190191 <select192 value={formData.category}193 onChange={(e) => setFormData({ ...formData, category: e.target.value })}194 >195 {state.categories.map(cat => (196 <option key={cat} value={cat}>{cat}</option>197 ))}198 </select>199200 <input201 type="date"202 value={formData.dueDate}203 onChange={(e) => setFormData({ ...formData, dueDate: e.target.value })}204 />205206 <div className="form-actions">207 <button type="button" onClick={onClose}>Cancel</button>208 <button type="submit">Add Task</button>209 </div>210 </form>211 );212}213214// Task Item Component215function TaskItem({ task }) {216 const { dispatch } = useApp();217 const [isEditing, setIsEditing] = useState(false);218219 const priorityColors = {220 low: 'green',221 medium: 'orange',222 high: 'red'223 };224225 return (226 <div className={`task-item ${task.completed ? 'completed' : ''}`}>227 <input228 type="checkbox"229 checked={task.completed}230 onChange={() => dispatch({ type: 'TOGGLE_TASK', payload: task.id })}231 />232233 <div className="task-content">234 <h3>{task.title}</h3>235 {task.description && <p>{task.description}</p>}236237 <div className="task-meta">238 <span239 className="priority"240 style={{ color: priorityColors[task.priority] }}241 >242 {task.priority}243 </span>244 <span className="category">{task.category}</span>245 {task.dueDate && (246 <span className="due-date">247 Due: {new Date(task.dueDate).toLocaleDateString()}248 </span>249 )}250 </div>251 </div>252253 <div className="task-actions">254 <button onClick={() => setIsEditing(true)}>Edit</button>255 <button256 onClick={() => dispatch({ type: 'DELETE_TASK', payload: task.id })}257 >258 Delete259 </button>260 </div>261 </div>262 );263}264265// Main App Component266function TaskApp() {267 const { state, dispatch } = useApp();268 const tasks = useTasks();269 const [showAddForm, setShowAddForm] = useState(false);270271 const stats = {272 total: state.tasks.length,273 completed: state.tasks.filter(t => t.completed).length,274 active: state.tasks.filter(t => !t.completed).length275 };276277 return (278 <div className="app">279 <header className="app-header">280 <h1>Task Manager</h1>281282 <div className="header-actions">283 <button284 onClick={() => dispatch({ type: 'TOGGLE_THEME' })}285 className="theme-toggle"286 >287 {state.theme === 'light' ? '🌙' : '☀️'}288 </button>289 </div>290 </header>291292 <div className="stats">293 <div className="stat">294 <span className="stat-value">{stats.total}</span>295 <span className="stat-label">Total</span>296 </div>297 <div className="stat">298 <span className="stat-value">{stats.active}</span>299 <span className="stat-label">Active</span>300 </div>301 <div className="stat">302 <span className="stat-value">{stats.completed}</span>303 <span className="stat-label">Completed</span>304 </div>305 </div>306307 <div className="filters">308 <input309 type="search"310 placeholder="Search tasks..."311 value={state.filter.search}312 onChange={(e) =>313 dispatch({ type: 'SET_FILTER', payload: { search: e.target.value } })314 }315 />316317 <select318 value={state.filter.category}319 onChange={(e) =>320 dispatch({ type: 'SET_FILTER', payload: { category: e.target.value } })321 }322 >323 <option value="all">All Categories</option>324 {state.categories.map(cat => (325 <option key={cat} value={cat}>{cat}</option>326 ))}327 </select>328329 <select330 value={state.filter.completed}331 onChange={(e) =>332 dispatch({ type: 'SET_FILTER', payload: { completed: e.target.value } })333 }334 >335 <option value="all">All Tasks</option>336 <option value="active">Active</option>337 <option value="completed">Completed</option>338 </select>339 </div>340341 <div className="task-list">342 {tasks.map(task => (343 <TaskItem key={task.id} task={task} />344 ))}345346 {tasks.length === 0 && (347 <div className="empty-state">348 <p>No tasks found. Add one to get started!</p>349 </div>350 )}351 </div>352353 <button354 className="fab"355 onClick={() => setShowAddForm(true)}356 >357 +358 </button>359360 {showAddForm && (361 <div className="modal">362 <div className="modal-content">363 <TaskForm onClose={() => setShowAddForm(false)} />364 </div>365 </div>366 )}367 </div>368 );369}370371// Root Component372export default function App() {373 return (374 <AppProvider>375 <TaskApp />376 </AppProvider>377 );378}
Next Steps: Your React Journey Continues
Congratulations! You've completed this React learning journey, but this is just the beginning. The React ecosystem is vast and constantly evolving. Let's explore what comes next and how to continue growing as a React developer.
Next Steps in Your React Journey
Advanced Topics to Explore
- Next.js: Full-stack React with SSR
- React Native: Build mobile apps
- State Management: Redux, Zustand, MobX
- Testing: Integration and E2E testing
Portfolio Project Ideas
- E-commerce platform with cart and checkout
- Social media app with real-time updates
- Project management tool with collaboration
- Learning platform with progress tracking
Staying Current
- Follow React blog for official updates
- Watch React conference talks
- Join React community discussions
- Practice with new features regularly
Contributing to Open Source
- Start with documentation improvements
- Find beginner-friendly issues
- Fix bugs before adding features
- Be patient and persistent
1// Learning Roadmap23// Phase 1: Fundamentals (You are here! ✅)4const fundamentals = {5 core: ['Components', 'Props', 'State', 'Hooks'],6 essential: ['useEffect', 'useContext', 'useReducer'],7 routing: ['React Router', 'Navigation'],8 testing: ['Jest', 'React Testing Library']9};1011// Phase 2: Advanced React (Next 3-6 months)12const advanced = {13 performance: ['React.memo', 'useMemo', 'useCallback', 'Code Splitting'],14 patterns: ['Compound Components', 'Custom Hooks', 'State Machines'],15 tooling: ['Webpack', 'ESLint', 'Prettier']16};1718// Phase 3: Full-Stack React (6-12 months)19const fullStack = {20 frameworks: ['Next.js', 'Remix', 'Gatsby'],21 backend: ['Node.js + Express', 'REST APIs', 'Authentication'],22 deployment: ['CI/CD', 'Docker', 'Cloud Platforms']23};2425// Learning Resources26const resources = {27 courses: ['Epic React by Kent C. Dodds', 'Full Stack Open'],28 youtube: ['Traversy Media', 'The Net Ninja', 'Web Dev Simplified'],29 practice: ['Frontend Mentor', 'React Coding Challenges']30};3132// Final Project Challenge33/*34Build a "React Learning Tracker" app that includes:35361. Track completed lessons/topics372. Set learning goals and deadlines383. Progress visualization with charts394. Note-taking for each topic405. Dark/light theme toggle416. Mobile responsive design4243This project will demonstrate:44- Complex state management45- Data persistence with localStorage46- Charts and visualizations47- Responsive design48- Accessibility best practices49*/