The Problem with Passing Props
In React, passing data through props can become cumbersome as your app grows. For example, if you need to pass data to deeply nested components, you have to pass the data through every intermediary component. This can lead to “prop drilling,” where you’re passing the same data through multiple layers of components.
This is where the Context API comes in. With Context API, you can store data at the top level of the component tree and make it available to all other components that need it without passing props.
The React Context API is a way to manage and share state across your application without having to pass props down through every level of your component tree. It helps manage global data that needs to be accessible by many components at different nesting levels.
Get Started with the Context API
It's a good practice to organize your React application by creating a separate folder for context files.
- Create a Context Object
Create a context object using the createContext function from the 'react' library. This context object will hold the data that you want to share across your application.
userContext.js
import React from "react";
const UserContext = React.createContext();
export default UserContext;
- Wrap Components with a Provider
Once you create a context object, you use its Provider
component to wrap the components that need access to the shared data. For example, if you create a UserContext
, you would wrap your components inside the <UserContext.Provider>
. This allows any component within that wrapper to access the shared data provided by the context.
It's important to note that the Provider component should be wrapped around the top-level component in an application to ensure that all child components have access to the shared data.
userContextProvider.jsx
import React from 'react'
import UserContext from "./userContext";
const userContextProvider = ({children}) => {
const [user, setUser] = React.useState(null);
return (
<UserContext.Provider value={{user, setUser}}>
{children}
</UserContext.Provider>
)
}
export default userContextProvider
app.jsx
import React from 'react'
import UserContextProvider from './context/userContextProvider'
import Login from './components/Login'
import Profile from './components/Profile'
function App() {
return (
<>
<UserContextProvider>
<Login/>
<Profile/>
</UserContextProvider>
</>
)
}
export default App
- useContext()
useContext() in React to access the data from a context that was provided by a Context.Provider. This hook allows any component inside the provider to easily "consume" or use the shared data without needing to pass it down through props.
- Writing Data
When we share data through context, we pass both reading and updating functions, like in the earlier example where we passed an array with user
(for reading) and setUser
(for writing or updating the data).
In real applications, we often use context to share multiple pieces of data, not just two. Depending on the functionality, you'll have different contexts for different purposes, like:
- A
UserContext
for managing user data (login, profile, etc.). - A
ThemeContext
for handling themes (dark mode, light mode). - An
AuthContext
for authentication states (logged in, logged out).
Each context can have its own file for organization, making it easier to manage and maintain the shared data for different parts of the app.
Login.jsx
import React from 'react'
import UserContext from '../context/userContext';
function Login() {
const [username, setUsername] = React.useState("");
const [password, setPassword] = React.useState("");
const {setUser} = React.useContext(UserContext);
const handleSubmit = (e) => {
e.preventDefault() //this prevent the data sending through post method to random location on clicking button
setUser({username, password}); //setUser for writing data.
};
return (
<div>
<input
type="text"
value={username}
onChange={(e) => setUsername(e.target.value)}
placeholder="Username"
/>
<input
type="text"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Password"
/>
<button onClick={handleSubmit}>Login</button>
</div>
);
}
export default Login
- Reading Data
Profile.jsx
import React from 'react'
import UserContext from '../context/userContext';
function Profile() {
const { user } = React.useContext(UserContext);
if (!user) return <div>Please Login.</div>
return (
<div>
Welcome User: {user.username}
</div>
);
}
export default Profile
Top comments (0)