Back to React JS Course

React JS Course

screenshot of the app

To avoid prop drilling, we need to make use of Context API in class components and useContext in functional components.

Now lets see useContext.

  • Accepts a context object(the value returned from createContext).
  • Returns the current context value for that context.
  • current context value is determined by value prop of the nearest <MyContext.Provider> above the calling component in the tree.

For example,

const themes = { light: { foreground: "#000000", background: "#eeeeee", }, dark: { foreground: "#ffffff", background: "#222222", }, }; const ThemeContext = React.createContext(themes.light); function App() { return ( <ThemeContext.Provider value={themes.dark}> <Toolbar /> </ThemeContext.Provider> ); } function Toolbar(props) { return ( <div> <ThemedButton /> </div> ); } function ThemedButton() { const theme = useContext(ThemeContext); return ( <button style={{ background: theme.background, color: theme.foreground }}> I am styled by theme context! </button> ); }

Let's consider a more realistic example using useContext in a scenario where you might have an authentication system. We'll create a context to manage the authentication status and user information across your application.

Create an Authentication Context

import React, { createContext, useState, useContext } from 'react'; // Create the Authentication Context const AuthContext = createContext(); export const useAuth = () => useContext(AuthContext); const AuthProvider = ({ children }) => { const [isAuthenticated, setIsAuthenticated] = useState(false); const [user, setUser] = useState(null); const login = (userInfo) => { setIsAuthenticated(true); setUser(userInfo); }; const logout = () => { setIsAuthenticated(false); setUser(null); }; return ( <AuthContext.Provider value={{ isAuthenticated, user, login, logout }}> {children} </AuthContext.Provider> ); }; export default AuthProvider;

Create Components to Use Authentication Context

Login Component

import React, { useState } from 'react'; import { useAuth } from './AuthProvider'; const Login = () => { const { login } = useAuth(); const [username, setUsername] = useState(''); const handleLogin = () => { login({ name: username }); setUsername(''); }; return ( <div> <input type="text" value={username} onChange={(e) => setUsername(e.target.value)} placeholder="Enter your username" /> <button onClick={handleLogin}>Login</button> </div> ); }; export default Login;

Logout Component

import React from 'react'; import { useAuth } from './AuthProvider'; const Logout = () => { const { logout } = useAuth(); return <button onClick={logout}>Logout</button>; }; export default Logout;

UserProfile Component

import React from 'react'; import { useAuth } from './AuthProvider'; const UserProfile = () => { const { isAuthenticated, user } = useAuth(); return ( <div> {isAuthenticated ? ( <div> <h1>Welcome, {user.name}!</h1> <Logout /> </div> ) : ( <p>Please log in.</p> )} </div> ); }; export default UserProfile;

Finally, wrap our application with the AuthProvider to make the authentication context available to your components.

import React from 'react'; import ReactDOM from 'react-dom'; import AuthProvider from './AuthProvider'; import Login from './Login'; import UserProfile from './UserProfile'; const App = () => ( <AuthProvider> <div> <UserProfile /> <Login /> </div> </AuthProvider> ); ReactDOM.render(<App />, document.getElementById('root'));

This setup allows you to manage authentication state across your application efficiently, ensuring that components can easily check if a user is logged in and manage user sessions.