Introduction
The Context API is a powerful feature in React that allows you to share state across the entire application (or part of it) without having to pass props down manually at every level. This is particularly useful for global data such as user authentication, theme settings, or language preferences.
Key Concepts
- Context Creation: Creating a context using
React.createContext()
. - Provider: A component that provides the context value to its children.
- Consumer: A component that consumes the context value.
- useContext Hook: A hook that allows functional components to consume context values.
Creating a Context
To create a context, you use the React.createContext()
function. This function returns an object with two properties: Provider
and Consumer
.
Providing Context
The Provider
component is used to wrap the part of your application where you want the context to be available. It accepts a value
prop, which will be passed to all consuming components.
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; const MyContext = React.createContext(); const MyProvider = ({ children }) => { const value = { user: 'John Doe' }; return ( <MyContext.Provider value={value}> {children} </MyContext.Provider> ); }; ReactDOM.render( <MyProvider> <App /> </MyProvider>, document.getElementById('root') );
Consuming Context
There are two main ways to consume context: using the Consumer
component or the useContext
hook.
Using the Consumer Component
The Consumer
component uses the render prop pattern to access the context value.
import React from 'react'; import { MyContext } from './MyProvider'; const MyComponent = () => ( <MyContext.Consumer> {value => <div>User: {value.user}</div>} </MyContext.Consumer> ); export default MyComponent;
Using the useContext Hook
The useContext
hook is a more modern and concise way to consume context in functional components.
import React, { useContext } from 'react'; import { MyContext } from './MyProvider'; const MyComponent = () => { const context = useContext(MyContext); return <div>User: {context.user}</div>; }; export default MyComponent;
Practical Example
Let's create a simple example where we manage a theme (light or dark) using the Context API.
Step 1: Create the Context
import React, { createContext, useState } from 'react'; const ThemeContext = createContext(); 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 { ThemeContext, ThemeProvider };
Step 2: Provide the Context
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; import { ThemeProvider } from './ThemeContext'; ReactDOM.render( <ThemeProvider> <App /> </ThemeProvider>, document.getElementById('root') );
Step 3: Consume the Context
import React, { useContext } from 'react'; import { ThemeContext } from './ThemeContext'; const ThemedComponent = () => { const { theme, toggleTheme } = useContext(ThemeContext); return ( <div style={{ background: theme === 'light' ? '#fff' : '#333', color: theme === 'light' ? '#000' : '#fff' }}> <p>The current theme is {theme}</p> <button onClick={toggleTheme}>Toggle Theme</button> </div> ); }; export default ThemedComponent;
Exercise
Task
- Create a context to manage user authentication status.
- Provide the context to your application.
- Consume the context in a component to display the user's authentication status and a button to toggle the status.
Solution
Step 1: Create the Context
import React, { createContext, useState } from 'react'; const AuthContext = createContext(); const AuthProvider = ({ children }) => { const [isAuthenticated, setIsAuthenticated] = useState(false); const toggleAuth = () => { setIsAuthenticated((prevAuth) => !prevAuth); }; return ( <AuthContext.Provider value={{ isAuthenticated, toggleAuth }}> {children} </AuthContext.Provider> ); }; export { AuthContext, AuthProvider };
Step 2: Provide the Context
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; import { AuthProvider } from './AuthContext'; ReactDOM.render( <AuthProvider> <App /> </AuthProvider>, document.getElementById('root') );
Step 3: Consume the Context
import React, { useContext } from 'react'; import { AuthContext } from './AuthContext'; const AuthStatus = () => { const { isAuthenticated, toggleAuth } = useContext(AuthContext); return ( <div> <p>User is {isAuthenticated ? 'Authenticated' : 'Not Authenticated'}</p> <button onClick={toggleAuth}>Toggle Authentication</button> </div> ); }; export default AuthStatus;
Conclusion
In this section, we learned about the Context API in React, which allows for efficient state management across different parts of an application. We covered how to create, provide, and consume context using both the Consumer
component and the useContext
hook. We also implemented a practical example to manage themes and an exercise to manage user authentication status. Understanding the Context API is crucial for managing global state in a React application, and it serves as a foundation for more advanced state management solutions like Redux.
React Course
Module 1: Introduction to React
- What is React?
- Setting Up the Development Environment
- Hello World in React
- JSX: JavaScript Syntax Extension
Module 2: React Components
- Understanding Components
- Functional vs Class Components
- Props: Passing Data to Components
- State: Managing Component State
Module 3: Working with Events
Module 4: Advanced Component Concepts
- Lifting State Up
- Composition vs Inheritance
- React Lifecycle Methods
- Hooks: Introduction and Basic Usage
Module 5: React Hooks
Module 6: Routing in React
Module 7: State Management
- Introduction to State Management
- Context API
- Redux: Introduction and Setup
- Redux: Actions and Reducers
- Redux: Connecting to React
Module 8: Performance Optimization
- React Performance Optimization Techniques
- Memoization with React.memo
- useMemo and useCallback Hooks
- Code Splitting and Lazy Loading
Module 9: Testing in React
- Introduction to Testing
- Unit Testing with Jest
- Testing Components with React Testing Library
- End-to-End Testing with Cypress
Module 10: Advanced Topics
- Server-Side Rendering (SSR) with Next.js
- Static Site Generation (SSG) with Next.js
- TypeScript with React
- React Native: Building Mobile Apps