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 Pattern
2import React, { createContext, useContext, useState } from 'react';
3
4const SelectContext = createContext();
5
6function Select({ children, defaultValue, onChange }) {
7 const [value, setValue] = useState(defaultValue);
8 const [isOpen, setIsOpen] = useState(false);
9
10 const updateValue = (newValue) => {
11 setValue(newValue);
12 setIsOpen(false);
13 onChange?.(newValue);
14 };
15
16 return (
17 <SelectContext.Provider value={{ value, isOpen, setIsOpen, updateValue }}>
18 <div className="select-container">
19 {children}
20 </div>
21 </SelectContext.Provider>
22 );
23}
24
25Select.Trigger = function SelectTrigger() {
26 const { value, isOpen, setIsOpen } = useContext(SelectContext);
27
28 return (
29 <button onClick={() => setIsOpen(!isOpen)}>
30 {value || 'Select an option'}
31 <span>{isOpen ? '▲' : '▼'}</span>
32 </button>
33 );
34};
35
36Select.Options = function SelectOptions({ children }) {
37 const { isOpen } = useContext(SelectContext);
38
39 if (!isOpen) return null;
40
41 return <div className="select-options">{children}</div>;
42};
43
44Select.Option = function SelectOption({ value, children }) {
45 const { value: selectedValue, updateValue } = useContext(SelectContext);
46
47 return (
48 <div
49 className={selectedValue === value ? 'selected' : ''}
50 onClick={() => updateValue(value)}
51 >
52 {children}
53 </div>
54 );
55};
56
57// Usage
58function 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}
69
70// Custom Hooks
71
72// useLocalStorage - Sync state with localStorage
73function 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 });
82
83 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 };
91
92 return [storedValue, setValue];
93}
94
95// useDebounce - Delay updates
96function useDebounce(value, delay) {
97 const [debouncedValue, setDebouncedValue] = useState(value);
98
99 useEffect(() => {
100 const timer = setTimeout(() => {
101 setDebouncedValue(value);
102 }, delay);
103
104 return () => clearTimeout(timer);
105 }, [value, delay]);
106
107 return debouncedValue;
108}
109
110// Usage example
111function SearchComponent() {
112 const [searchTerm, setSearchTerm] = useState('');
113 const debouncedSearch = useDebounce(searchTerm, 500);
114 const [savedSearches, setSavedSearches] = useLocalStorage('searches', []);
115
116 useEffect(() => {
117 if (debouncedSearch) {
118 console.log('Searching for:', debouncedSearch);
119 }
120 }, [debouncedSearch]);
121
122 return (
123 <div>
124 <input
125 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}
134
135// 🚦 STATE MACHINES WITH useReducer
136
137// Complex form with multiple steps
138const 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};
171
172function formReducer(state, action) {
173 const nextState = formMachine.states[state.status]?.on?.[action.type];
174
175 if (!nextState) {
176 return state;
177 }
178
179 return {
180 ...state,
181 status: nextState,
182 ...action.payload
183 };
184}
185
186function MultiStepForm() {
187 const [state, dispatch] = useReducer(formReducer, {
188 status: formMachine.initial,
189 data: {},
190 errors: {}
191 });
192
193 const handleSubmit = async (formData) => {
194 dispatch({ type: 'SUBMIT' });
195
196 // Validate
197 const errors = validateForm(formData);
198 if (Object.keys(errors).length > 0) {
199 dispatch({ type: 'INVALID', payload: { errors } });
200 return;
201 }
202
203 dispatch({ type: 'VALID' });
204
205 try {
206 await submitForm(formData);
207 dispatch({ type: 'SUCCESS' });
208 } catch (error) {
209 dispatch({ type: 'ERROR', payload: { error: error.message } });
210 }
211 };
212
213 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 )}
224
225 {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 Another
232 </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 App
2import React, { createContext, useContext, useReducer, useEffect, useState } from 'react';
3
4const AppContext = createContext();
5
6const 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};
17
18function appReducer(state, action) {
19 switch (action.type) {
20 case 'SET_USER':
21 return { ...state, user: action.payload };
22
23 case 'ADD_TASK':
24 return {
25 ...state,
26 tasks: [...state.tasks, action.payload]
27 };
28
29 case 'UPDATE_TASK':
30 return {
31 ...state,
32 tasks: state.tasks.map(task =>
33 task.id === action.payload.id ? action.payload : task
34 )
35 };
36
37 case 'DELETE_TASK':
38 return {
39 ...state,
40 tasks: state.tasks.filter(task => task.id !== action.payload)
41 };
42
43 case 'TOGGLE_TASK':
44 return {
45 ...state,
46 tasks: state.tasks.map(task =>
47 task.id === action.payload
48 ? { ...task, completed: !task.completed, updatedAt: new Date() }
49 : task
50 )
51 };
52
53 case 'SET_FILTER':
54 return {
55 ...state,
56 filter: { ...state.filter, ...action.payload }
57 };
58
59 case 'TOGGLE_THEME':
60 return {
61 ...state,
62 theme: state.theme === 'light' ? 'dark' : 'light'
63 };
64
65 case 'REORDER_TASKS':
66 return {
67 ...state,
68 tasks: action.payload
69 };
70
71 default:
72 return state;
73 }
74}
75
76// 3. MAIN APP PROVIDER
77function AppProvider({ children }) {
78 const [state, dispatch] = useReducer(appReducer, initialState, (initial) => {
79 // Load from localStorage
80 const saved = localStorage.getItem('taskapp_state');
81 return saved ? { ...initial, ...JSON.parse(saved) } : initial;
82 });
83
84 // Persist to localStorage
85 useEffect(() => {
86 localStorage.setItem('taskapp_state', JSON.stringify(state));
87 }, [state]);
88
89 // Apply theme
90 useEffect(() => {
91 document.documentElement.setAttribute('data-theme', state.theme);
92 }, [state.theme]);
93
94 return (
95 <AppContext.Provider value={{ state, dispatch }}>
96 {children}
97 </AppContext.Provider>
98 );
99}
100
101// 4. CUSTOM HOOKS
102function useApp() {
103 const context = useContext(AppContext);
104 if (!context) {
105 throw new Error('useApp must be used within AppProvider');
106 }
107 return context;
108}
109
110function useTasks() {
111 const { state } = useApp();
112 const { tasks, filter } = state;
113
114 // Filter tasks based on current filter
115 return tasks.filter(task => {
116 if (filter.category !== 'all' && task.category !== filter.category) {
117 return false;
118 }
119
120 if (filter.completed === 'active' && task.completed) {
121 return false;
122 }
123
124 if (filter.completed === 'completed' && !task.completed) {
125 return false;
126 }
127
128 if (filter.search && !task.title.toLowerCase().includes(filter.search.toLowerCase())) {
129 return false;
130 }
131
132 return true;
133 });
134}
135
136// 5. MAIN COMPONENTS
137function 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 });
147
148 const handleSubmit = (e) => {
149 e.preventDefault();
150
151 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) : undefined
158 };
159
160 dispatch({ type: 'ADD_TASK', payload: newTask });
161 onClose();
162 };
163
164 return (
165 <form onSubmit={handleSubmit} className="task-form">
166 <h2>Add New Task</h2>
167
168 <input
169 type="text"
170 placeholder="Task title"
171 value={formData.title}
172 onChange={(e) => setFormData({ ...formData, title: e.target.value })}
173 required
174 />
175
176 <textarea
177 placeholder="Description (optional)"
178 value={formData.description}
179 onChange={(e) => setFormData({ ...formData, description: e.target.value })}
180 />
181
182 <select
183 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>
190
191 <select
192 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>
199
200 <input
201 type="date"
202 value={formData.dueDate}
203 onChange={(e) => setFormData({ ...formData, dueDate: e.target.value })}
204 />
205
206 <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}
213
214// Task Item Component
215function TaskItem({ task }) {
216 const { dispatch } = useApp();
217 const [isEditing, setIsEditing] = useState(false);
218
219 const priorityColors = {
220 low: 'green',
221 medium: 'orange',
222 high: 'red'
223 };
224
225 return (
226 <div className={`task-item ${task.completed ? 'completed' : ''}`}>
227 <input
228 type="checkbox"
229 checked={task.completed}
230 onChange={() => dispatch({ type: 'TOGGLE_TASK', payload: task.id })}
231 />
232
233 <div className="task-content">
234 <h3>{task.title}</h3>
235 {task.description && <p>{task.description}</p>}
236
237 <div className="task-meta">
238 <span
239 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>
252
253 <div className="task-actions">
254 <button onClick={() => setIsEditing(true)}>Edit</button>
255 <button
256 onClick={() => dispatch({ type: 'DELETE_TASK', payload: task.id })}
257 >
258 Delete
259 </button>
260 </div>
261 </div>
262 );
263}
264
265// Main App Component
266function TaskApp() {
267 const { state, dispatch } = useApp();
268 const tasks = useTasks();
269 const [showAddForm, setShowAddForm] = useState(false);
270
271 const stats = {
272 total: state.tasks.length,
273 completed: state.tasks.filter(t => t.completed).length,
274 active: state.tasks.filter(t => !t.completed).length
275 };
276
277 return (
278 <div className="app">
279 <header className="app-header">
280 <h1>Task Manager</h1>
281
282 <div className="header-actions">
283 <button
284 onClick={() => dispatch({ type: 'TOGGLE_THEME' })}
285 className="theme-toggle"
286 >
287 {state.theme === 'light' ? '🌙' : '☀️'}
288 </button>
289 </div>
290 </header>
291
292 <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>
306
307 <div className="filters">
308 <input
309 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 />
316
317 <select
318 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>
328
329 <select
330 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>
340
341 <div className="task-list">
342 {tasks.map(task => (
343 <TaskItem key={task.id} task={task} />
344 ))}
345
346 {tasks.length === 0 && (
347 <div className="empty-state">
348 <p>No tasks found. Add one to get started!</p>
349 </div>
350 )}
351 </div>
352
353 <button
354 className="fab"
355 onClick={() => setShowAddForm(true)}
356 >
357 +
358 </button>
359
360 {showAddForm && (
361 <div className="modal">
362 <div className="modal-content">
363 <TaskForm onClose={() => setShowAddForm(false)} />
364 </div>
365 </div>
366 )}
367 </div>
368 );
369}
370
371// Root Component
372export 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

  1. E-commerce platform with cart and checkout
  2. Social media app with real-time updates
  3. Project management tool with collaboration
  4. 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 Roadmap
2
3// 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};
10
11// 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};
17
18// 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};
24
25// Learning Resources
26const 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};
31
32// Final Project Challenge
33/*
34Build a "React Learning Tracker" app that includes:
35
361. Track completed lessons/topics
372. Set learning goals and deadlines
383. Progress visualization with charts
394. Note-taking for each topic
405. Dark/light theme toggle
416. Mobile responsive design
42
43This project will demonstrate:
44- Complex state management
45- Data persistence with localStorage
46- Charts and visualizations
47- Responsive design
48- Accessibility best practices
49*/