Advanced React Development

Master advanced React patterns, state management, performance optimization, and testing.

advanced Frontend Frameworks 8 hours

Chapter 3: Context API Advanced Usage

Chapter 3 of 15

Chapter 3: Context API Advanced Usage

3.1 Multiple Contexts

Large applications often need multiple contexts for different concerns. Properly organizing and using multiple contexts prevents prop drilling.

// Theme Context
const ThemeContext = React.createContext('light');

// User Context
const UserContext = React.createContext(null);

// Auth Context
const AuthContext = React.createContext({ isAuthenticated: false });

// Using multiple contexts
function App() {
    return (
        <ThemeContext.Provider value="dark">
            <UserContext.Provider value={{ name: 'John' }}>
                <AuthContext.Provider value={{ isAuthenticated: true }}>
                    <MyComponent />
                </AuthContext.Provider>
            </UserContext.Provider>
        </ThemeContext.Provider>
    );
}

function MyComponent() {
    const theme = useContext(ThemeContext);
    const user = useContext(UserContext);
    const auth = useContext(AuthContext);
    
    return <div className={theme}>Welcome {user.name}</div>;
}

3.2 Context Composition

// Combine multiple contexts
function AppProviders({ children }) {
    return (
        <ThemeProvider>
            <UserProvider>
                <AuthProvider>
                    {children}
                </AuthProvider>
            </UserProvider>
        </ThemeProvider>
    );
}

3.3 Custom Context Hooks

// Create custom hook for context
function useTheme() {
    const context = useContext(ThemeContext);
    if (!context) {
        throw new Error('useTheme must be used within ThemeProvider');
    }
    return context;
}

// Usage
function Component() {
    const theme = useTheme(); // Cleaner API
    return <div className={theme}>Content</div>;
}

3.4 Context Performance Optimization

// Split contexts to prevent unnecessary re-renders
const UserStateContext = React.createContext();
const UserDispatchContext = React.createContext();

function UserProvider({ children }) {
    const [state, dispatch] = useReducer(userReducer, initialState);
    
    return (
        <UserStateContext.Provider value={state}>
            <UserDispatchContext.Provider value={dispatch}>
                {children}
            </UserDispatchContext.Provider>
        </UserStateContext.Provider>
    );
}

// Components only re-render when needed
function UserName() {
    const state = useContext(UserStateContext); // Only re-renders on state change
    return <div>{state.name}</div>;
}