The React Context API is a tool for managing state globally in a React application. It allows you to share values (like state or functions) between components without passing props manually down through the component tree.
Why Use Context API?
- To avoid “prop drilling” (passing props through multiple levels of components).
- To manage global state (e.g., user authentication, themes, or application settings).
- It’s simpler and lighter than state management libraries like Redux for certain use cases.
How Does the Context API Work?
The Context API has three main components:
- Context Provider: Supplies the data to components.
- Context Consumer: Consumes the data from the provider.
- React.useContext Hook: Simplifies consuming the context.
Basic Steps to Use Context API
1. Create a Context
import React, { createContext } from 'react'; const MyContext = createContext(); // Create the context export default MyContext;
2. Provide the Context
Wrap your components with the context Provider and pass the value to share.
import React, { useState } from 'react'; import MyContext from './MyContext'; const App = () => { const [user, setUser] = useState('John Doe'); return ( <MyContext.Provider value={{ user, setUser }}> <Child /> </MyContext.Provider> ); }; const Child = () => { return <Grandchild />; }; const Grandchild = () => { return <p>I am the grandchild component.</p>; }; export default App;
3. Consume the Context
There are two ways to consume the context:
- Using
useContext
Hook (Recommended for Functional Components):import React, { useContext } from 'react'; import MyContext from './MyContext'; const Grandchild = () => { const { user } = useContext(MyContext); return <p>Logged-in user: {user}</p>; };
- Using the Consumer Component (Older Method):
import React from 'react'; import MyContext from './MyContext'; const Grandchild = () => { return ( <MyContext.Consumer> {({ user }) => <p>Logged-in user: {user}</p>} </MyContext.Consumer> ); };
Real-World Example: Theme Context
1. Create the Context
import React, { createContext, useState } from 'react'; const ThemeContext = createContext(); export const ThemeProvider = ({ children }) => { const [theme, setTheme] = useState('light'); const toggleTheme = () => { setTheme((prevTheme) => (prevTheme === 'light' ? 'dark' : 'light')); }; return ( <ThemeContext.Provider value={{ theme, toggleTheme }}> {children} </ThemeContext.Provider> ); }; export default ThemeContext;
2. Use the Provider in the App
import React from 'react'; import { ThemeProvider } from './ThemeContext'; import ThemeToggler from './ThemeToggler'; const App = () => { return ( <ThemeProvider> <ThemeToggler /> </ThemeProvider> ); }; export default App;
3. Consume the Context
import React, { useContext } from 'react'; import ThemeContext from './ThemeContext'; const ThemeToggler = () => { const { theme, toggleTheme } = useContext(ThemeContext); return ( <div> <p>Current Theme: {theme}</p> <button onClick={toggleTheme}>Toggle Theme</button> </div> ); }; export default ThemeToggler;
When to Use Context API
- Use for global state like:
- Themes (light/dark mode)
- User authentication (logged-in user data)
- Language preferences (i18n)
- Avoid using it for frequent updates or performance-critical data (use local state or libraries like Redux or Zustand).
Best Practices
- Avoid Overusing Context: Don’t replace local state with context unless needed.
- Split Contexts: Use multiple contexts for unrelated data (e.g., one for theme, one for user).
- Memoize Values: Use
useMemo
for derived values in the provider to avoid unnecessary re-renders.const value = useMemo(() => ({ user, setUser }), [user]); <MyContext.Provider value={value}>{children}</MyContext.Provider>;
- Combine with Other Tools: Use alongside tools like
React.memo
orReact.lazy
for optimized performance.