React
I. React Fundamentals
1. Introduction to React
2. React vs JavaScript
3. Setting Up React Environment
4. JSX Basics
5. Components Overview
6. Functional Components
7. Props
8. State Basics
II. Core React Concepts
9. Event Handling
10. Conditional Rendering
11. Lists and Keys
12. Forms in React
13. Controlled Components
14. useEffect Hook
15. useState Hook
16. Custom Hooks
III. Adv. React & Ecosystem
17. Context API
18. React Router
19. API Calls with Fetch
20. API Calls with Axios
21. Lifting State Up
22. Performance Optimization
23. Code Splitting
24. Error Boundaries
IV. Projects & Practices
25. React Best Practices
26. Folder Structure
27. Testing React Components
28. Security in React
29. React Interview Questions
30. Mini Project – Todo App
31. Mini Project – Dashboard
32. Mini Project – Ecommerce UI
33. Mini Project – API Integration
34. React Case Study
35. React Real-World Use Cases
36. React Project Planning
37. React Final Project
38. React Deployment
39. React Course Review
40. React Wrap-Up
41. Advanced React Patterns
42. React with TypeScript
43. React Accessibility
44. React Performance Audit
45. React Career Roadmap
LESSON 41
Advanced React Patterns
Master compound components, render props, higher-order components, and custom hooks to build flexible, reusable UI systems.
React patterns solve real problems. When you build the same component five times with slight variations, patterns help you create one flexible solution. These aren't academic concepts — they're tools Netflix uses for their video player controls and Airbnb uses for their booking forms.Compound Components
A compound component works like HTML'sselect and option tags. The parent manages state while children handle their own rendering. React's Context API makes this possible.
Think of it like a restaurant menu. The menu container holds all the logic, but each menu item knows how to display itself:
// Menu compound component for DataFlow filters
const Menu = ({ children, onSelect }) => {
const [isOpen, setIsOpen] = useState(false);
const [selected, setSelected] = useState('');
const value = { isOpen, setIsOpen, selected, setSelected, onSelect };
return (
<MenuContext.Provider value={value}>
<div className="menu">{children}</div>
</MenuContext.Provider>
);
};DataFlow Dashboard
What just happened?
The Menu component shares state through Context while each subcomponent handles its own rendering logic. The dot notation (Menu.Toggle) creates a clean API that feels like native HTML elements. Try this: Add more Menu.Item components to see how flexible this pattern becomes.
The Menu component shares state through Context while each subcomponent handles its own rendering logic. The dot notation (Menu.Toggle) creates a clean API that feels like native HTML elements. Try this: Add more Menu.Item components to see how flexible this pattern becomes.
Render Props Pattern
Render props let you share code between components using a prop whose value is a function. Instead of guessing what UI someone wants, you let them tell you. The DataFlow team needs flexible data loading. Sometimes they want a spinner, sometimes a progress bar, sometimes nothing. Render props solve this:// Flexible data fetcher with render props
const DataFetcher = ({ url, render }) => {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
// Simulate API call
setTimeout(() => {
setData({ revenue: 45200, users: 1340 });
setLoading(false);
}, 1500);
}, [url]);
return render({ data, loading, error });
};DataFlow Dashboard
What just happened?
The DataFetcher component handles all the loading logic but lets you decide how to render the UI. The render prop receives data and lets you create any UI you want. Try this: Change the render function to show a simple list instead of cards.
The DataFetcher component handles all the loading logic but lets you decide how to render the UI. The render prop receives data and lets you create any UI you want. Try this: Change the render function to show a simple list instead of cards.
Higher-Order Components (HOCs)
A higher-order component is a function that takes a component and returns a new component with extra functionality. Think of it like a decorator pattern — you wrap components to add features. Authentication is perfect for HOCs. The DataFlow admin panel needs to check if users are logged in before showing certain components:// HOC for authentication in DataFlow
const withAuth = (WrappedComponent) => {
return function AuthComponent(props) {
const [isLoggedIn, setIsLoggedIn] = useState(false);
const [loading, setLoading] = useState(true);
useEffect(() => {
// Simulate auth check
setTimeout(() => {
setIsLoggedIn(Math.random() > 0.3); // 70% chance logged in
setLoading(false);
}, 1000);
}, []);
if (loading) return <div>Checking authentication...</div>;
if (!isLoggedIn) return <div>Please log in to access DataFlow</div>;
return <WrappedComponent {...props} />;
};
};DataFlow Dashboard
What just happened?
The withAuth HOC wraps any component and adds authentication logic. The wrapped component only renders when the user is logged in — otherwise it shows an access denied message. Try this: Refresh the page multiple times to see different authentication states.
The withAuth HOC wraps any component and adds authentication logic. The wrapped component only renders when the user is logged in — otherwise it shows an access denied message. Try this: Refresh the page multiple times to see different authentication states.
Custom Hook Patterns
Custom hooks extract stateful logic into reusable functions. They're like regular functions but can use other hooks inside them. Every custom hook starts with "use" — that's the rule. The DataFlow team needs to fetch data from multiple endpoints. Instead of copying useEffect code everywhere, create a custom hook:// Custom hook for DataFlow API calls
const useDataFlowAPI = (endpoint, defaultValue = null) => {
const [data, setData] = useState(defaultValue);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const refetch = useCallback(() => {
setLoading(true);
setError(null);
// Simulate API call with realistic delay
setTimeout(() => {
const mockData = {
'/stats': { revenue: 89400, users: 2340, orders: 156 },
'/users': [{ id: 1, name: 'Sarah Chen', role: 'Admin' }],
'/orders': [{ id: 101, amount: 299, status: 'completed' }]
};
setData(mockData[endpoint] || defaultValue);
setLoading(false);
}, Math.random() * 1000 + 500);
}, [endpoint, defaultValue]);
useEffect(() => {
refetch();
}, [refetch]);
return { data, loading, error, refetch };
};DataFlow Dashboard
What just happened?
The useDataFlowAPI custom hook encapsulates all the data fetching logic. Both components use the same hook but with different endpoints. Each component gets its own state and can refetch independently. Try this: Click the refresh buttons to see independent loading states.
The useDataFlowAPI custom hook encapsulates all the data fetching logic. Both components use the same hook but with different endpoints. Each component gets its own state and can refetch independently. Try this: Click the refresh buttons to see independent loading states.
Provider Pattern
The Provider pattern uses React Context to share data across many components without prop drilling. Think of it as a global state that any component can access. DataFlow needs a theme system. Users should switch between light and dark modes anywhere in the app:// Theme provider for DataFlow
const ThemeContext = createContext();
export const ThemeProvider = ({ children }) => {
const [theme, setTheme] = useState('light');
const [primaryColor, setPrimaryColor] = useState('#047857');
const toggleTheme = () => {
setTheme(prev => prev === 'light' ? 'dark' : 'light');
};
const value = {
theme,
primaryColor,
toggleTheme,
setPrimaryColor,
colors: theme === 'light'
? { bg: '#ffffff', text: '#1f2937', border: '#e5e7eb' }
: { bg: '#1f2937', text: '#f9fafb', border: '#374151' }
};
return (
<ThemeContext.Provider value={value}>
{children}
</ThemeContext.Provider>
);
};DataFlow Dashboard
What just happened?
The ThemeProvider wraps the entire app and provides theme data to any component that needs it. Components use the useTheme hook to access colors and toggle functions without prop drilling. Try this: Click the theme toggle to see all components update their styling instantly.
The ThemeProvider wraps the entire app and provides theme data to any component that needs it. Components use the useTheme hook to access colors and toggle functions without prop drilling. Try this: Click the theme toggle to see all components update their styling instantly.
Pattern Selection Guide
Compound Components: When you need flexible composition (like HTML select/option)
Render Props: When you want to share logic but let consumers control rendering
HOCs: When you need to add the same functionality to multiple components
Custom Hooks: When you want to share stateful logic between components
Provider: When many components need the same data (auth, theme, settings)
Real apps combine these patterns. Netflix uses render props for their video player, compound components for navigation menus, and providers for user authentication. Linear uses custom hooks for their API calls and HOCs for permission checking.
The key is knowing when each pattern solves your specific problem. Start simple, then add patterns when you find yourself copying code or drilling props through many levels.
Compound Components: When you need flexible composition (like HTML select/option)
Render Props: When you want to share logic but let consumers control rendering
HOCs: When you need to add the same functionality to multiple components
Custom Hooks: When you want to share stateful logic between components
Provider: When many components need the same data (auth, theme, settings)
Quiz
1. How do compound components work in the DataFlow menu system?
2. What is a Higher-Order Component (HOC) in the DataFlow authentication system?
3. What's the main difference between custom hooks and render props for the DataFlow API system?
React with TypeScript
Add type safety to your React components and catch errors before they reach production.