Introduction
In the previous part I have explained about the basic idea behind the useReducer()
hooks. In this article I will try to explain about another useful hook useContext
. We will discus about how to use what useContext
is and how to use it. We will also discus about Context
API.
The Problem
Consider a React-Native application having nested component and you have to pass the data to child at the bottom level. Let me explain the problem with a simple code sample.
const App = () => {
const [info, SetUserInfo] = useState({
name: 'Rajshekhar',
about: 'Mobile Application Developer',
});
return (
<SafeAreaView style={styles.parent}>
<Component1 userInfo={info} />
</SafeAreaView>
);
};
const Component1 = props => {
return (
<View style={styles.sectionContainer}>
<Text style={styles.sectionTitle}>
This is Level 1. We don't need user info
</Text>
<Component2 userInfo={props.userInfo}></Component2>
</View>
);
};
const Component2 = props => {
return (
<View style={styles.sectionContainer}>
<Text style={styles.sectionSubtitle}>
This is Level 2. We don't need user info
</Text>
<Component3 userInfo={props.userInfo}></Component3>
</View>
);
};
const Component3 = props => {
return (
<View style={styles.sectionContainer}>
<Text style={styles.sectionDescription}>
This is Level 3. I need the user info.
</Text>
<Text style={styles.sectionDescription}>Hi {props.userInfo.name}!!</Text>
</View>
);
};
};
return (
<SafeAreaView style={styles.parent}>
<Component1 userName={name} />
</SafeAreaView>
);
};
As you can see, We need to explicitly pass the props
to even those components which do not even use it only to make the data available to the hierarchy below. We are maintaining the overhead of constantly passing the props
data throughout the entire Hierarchy.
I hope you are able to understand about the problem which I am trying to explain with the above code snippet. To solve this problem we have a rescuer Context API
.
Context API
Context API provides a way to pass the data to component tree without passing the data to every level. Context API reduces the coupling between the non related components. For Implementing Context ApI we need below things
- We have to create a
Context
, using React'screateContext()
method. - We will use the
Provider
in the high-level component to provide the Context Value. - We will then Consume the Context value using render props pattern.
export const UserInfoContext = React.createContext();
const App = () => {
const [info, SetUserInfo] = useState({
name: 'Rajshekhar',
about: 'Mobile Application Developer',
});
return (
<SafeAreaView style={styles.parent}>
<UserInfoContext.Provider value={info}>
<Component1 />
</UserInfoContext.Provider>
</SafeAreaView>
);
};
const Component3 = () => {
return (
<UserInfoContext.Consumer>
{userInfo => {
return (
<View style={styles.sectionContainer}>
<Text style={styles.sectionDescription}>
This is Level 3. I need the user info.
</Text>
<Text style={styles.sectionDescription}>Hi {userInfo.name}!!</Text>
</View>
);
}}
</UserInfoContext.Consumer>
);
};
Let me explain you the above code snippet.
- I have created a
UserInfoContext
by callingReact.createContext()
- For providing the context , we have to wrap our parent component with
UserInfoContext.Provider
. - Then we have to provide the value that we want pass down the component tree on
value
prop - For consuming the provided information, we have to wrap our child (who need the data ) with
UserInfoContext.Consumer
component.
I found one problem with this approach. Suppose we have multiple context, then things go ugly when we consume the provided value from Provider
return (
<UserInfoContext.Consumer>
{userInfo => {
return (
<NetworkContext.Consumer>
{status => {
return (
<View style={styles.sectionContainer}>
<Text style={styles.sectionDescription}>
This is Level 3. I need the user info.
</Text>
<Text style={styles.sectionDescription}>
NetworkStatus : {status}
</Text>
<Text style={styles.sectionDescription}>
Hi {userInfo.name}!!
</Text>
</View>
);
}}
</NetworkContext.Consumer>
);
}}
</UserInfoContext.Consumer>
This code will work. But for the shake of readability, I personally don't like it.
I hope I am able to explain the basic idea of Context API
.
useContext()
As we discussed about the Context API
. useContext
is another way of consuming context. It accepts a context object and returns the current context value for the that context.
Declaring the useContext()
Import the useContext()
package from react
.
import React, { useContext} from 'react';
Creating a context
We can create a context by using React.createContext()
export const UserInfoContext = React.createContext();
Provide Context to Components
For providing the value to our component. We have to wrap our component with Provider
Component.
<UserInfoContext.Provider value={info}>
<SafeAreaView style={styles.parent}>
<Component1 />
</SafeAreaView>
</UserInfoContext.Provider>
Consuming the context
Instead of using render props, we can pass the entire context object to React.useContext()
to consume context at the top of our component.
const userInfo = useContext(UserInfoContext);
return (
<View style={styles.sectionContainer}>
<Text style={styles.sectionDescription}>
This is Level 3. I need the user info.
</Text>
<Text style={styles.sectionDescription}>Hi {userInfo.name}!!</Text>
</View>
);
Don’t forget that the argument to useContext must be the context object itself:
useContext(MyContext.Consumer) | ❌ |
useContext(MyContext.Provider) | ❌ |
useContext(MyContext) | ✅ |
Conclusion
Let's take down key points about useContext()
Hook.
- It removes the overhead of passing the data via
props
through a nested component. In a simple word, if you want the data just consume it. - We can follow three simple steps to use it.
- Create a context with the help of
React.createContext()
. - Wrap the parent component with
YourContext.Provider
component and pass the value - Consume it wherever it is needed with the
useContext(YourContext)
.
- Create a context with the help of
Thanks for reading this article. I have tried to explain my understanding about useContext
hooks. Feel free to add suggestion. Let's connect on Twitter
Top comments (1)
Thank you so much for this great explanation! I'm currently learning React (Native) and this helps a lot. Thanks again.