Simplifying Data Sharing in React: An Introduction to the Context API
A Beginner's Guide to the React Context API and Its Practical Applications
One of the features that make React powerful is its ability to manage and share states between components. The Context API is a way to share state between components without having to pass props down through multiple levels of the component tree. In this blog post, we'll explore what the Context API is, how it works, and how to use it in a React application.
The Context API consists of two main parts: the Provider and the Consumer. The Provider is a component that wraps around other components and provides the state. The Consumer is a component that can access the state provided by the Provider.
How to Use Context API
There are three stages involved in using context API in react
Creating the context
Providing the context
Consuming the context
Stage 1: Creating the Context
To use the Context API, you first need to create a context using the createContext
function. This function takes an optional default value as an argument. Here's an example of how to create a context for a user's name:
const UserContext = React.createContext();
Stage 2: Providing the Context
Once you have created a context, you can use it to provide a state to your components. To do this, you need to wrap the components that will provide the state in a Provider component. The Provider component takes a value prop, which is the state that you want to share. Here's an example of how to use the UserContext Provider to provide a user's name:
<UserContext.Provider value={user.name}>
<App />
</UserContext.Provider>
Stage 3: Consuming the Context
There are two ways to consume a context:
Using the
consumer
componentUsing the
useContext()
hook
The Consumer Component
Once you have provided the state, you can access it using the Consumer component. The Consumer component takes a function as a child, which is called with the value provided by the Provider. Here's an illustration of how to use the UserContext Consumer to display a user's name:
<UserContext.Consumer>
{userName => <p>Welcome, {userName}</p>}
</UserContext.Consumer>
The Consumer component can be used inside any component that needs to access the state provided by the Provider. This way, you don't need to pass props down through multiple levels of the component tree just to share state between components.
The useContext()
Hook
The useContext
hook is a React hook that lets you read and subscribe to context from your component. The useContext
hook accepts a context object( the value returned from the createContext( )
). It is determined as the value passed to the closest Context.Provider
import { useContext } from 'react'
function myComponent() {
const userName = useContext(context);
return <p>Welcome, {userName}</p>
}
The Context API also makes it easy to update the state. To do this, you simply need to update the value prop of the Provider component. All the components that are using the Consumer component will automatically re-render with the new state.
Practical Applications of Context API
Managing Global state
Simplifying Data Flow
Improving Code Reusability
Dynamic Themeing
Language Localization
Managing User Authentication and Authorization
Accessing Third-Party APIs
Storing and Managing Form Data
Managing Loading States
Managing Error States
Let's look at one of the practical applications above to get a better view of context API
Dynamic Themeing
The Context API can be used to store and manage the theme of an application, allowing for easy switching between themes.
To begin, let's start by setting up a quick react app by typing this command in your terminal: npx create-react-app context
, then we should create a component folder and inside our component folder, we should create a themeContext component.
The structure of our react project should look like this:
First of all, we will create our ThemeContext which we will use in our application. we will then declare a isDarkTheme
variable and set it to false by default. Then we will declare a toggleTheme
function to switch the value of the isDarkTheme
. The application's theme-related functionality will be controlled by this state since it determines how all associated CSS is added or removed.
import React, { createContext, useState } from "react"
export const ThemeContext = createContext({
isDarkTheme: false,
toggleTheme: () => {},
})
const ThemeProvider = ({ children }) => {
const [isDarkTheme, setIsDarkTheme] = useState(false);
const toggleTheme = () => {
setIsDarkTheme(!isDarkTheme)
}
return (
<ThemeContext.Provider value={{ isDarkTheme, toggleTheme }}>
{children}
</ThemeContext.Provider>
)
}
export default ThemeProvider
To use our isDarkTheme
variable and toggleTheme
function, we need to first wrap our App component in the index.js
file with the ThemeProvider
component
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import ThemeProvider from "./components/ThemeContext"
import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<ThemeProvider>
<App />
</ThemeProvider>
</React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
Now we bring in the useContext
hook, and pass in the ThemeContext
as an argument to the hook to consume our global state variables in our App.js
components
import React, { useContext } from "react"
import "./App.css"
import { ThemeContext } from "./components/ThemeContext"
const App = () => {
const { isDarkTheme, toggleTheme } = useContext(ThemeContext)
return (
<div className={`app ${isDarkTheme === true ? "dark" : ""}`}>
<button
className={`button ${isDarkTheme === true ? "dark" : ""}`}
onClick={toggleTheme.bind(null)}>{`Switch to ${
isDarkTheme === true ? "Light Theme" : "Dark Theme"
}`}</button>
</div>
)
}
export default App
To conclude our small app, we need to include our styles for light and dark modes. When we set isDarkMode to true, dark-mode CSS will replace the default values and the light theme will be loaded by default.
:root {
--bg-light: #f4f4f4;
--bg-dark: #232323;
--text-light: var(--bg-dark);
--text-dark: var(--bg-light);
--transition: 0.3s;
}
* {
padding: 0;
margin: 0;
box-sizing: border-box;
transition: all var(--transition);
}
.app {
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: var(--bg-light);
}
.app.dark {
background: var(--bg-dark);
}
.button {
padding: 1rem;
border: none;
border-radius: 0.3rem;
min-width: 15rem;
font-size: 1rem;
cursor: pointer;
background: var(--bg-dark);
color: var(--text-dark);
border: 1px solid var(--bg-dark);
}
.button.dark {
background: var(--bg-light);
color: var(--text-light);
}
Then the final result of our small application will be:
Conclusion
The Context API is a great way to share state between components without having to pass props down through multiple levels of the component tree. It's a powerful feature that makes it easy to manage and share state in a large React application.
One of the biggest advantages of Context API over other state management libraries such as redux is that it's a simpler and less complex way to manage state. It's typically used for state that is not specific to one component but is needed by multiple components in the application. The Context API is also a great option when you don't need all the features that redux provides, such as middleware and time-travel debugging.
If you enjoyed this article and found it interesting, make sure to drop a comment and thumb up. See you next time โ๐ฟ.