Disclaimer: I also have a Context api tutorial for React components created using classes.
React has the concept of props, we pass props from one component into another. For React Applications, where data is passed in one direction, this can make things confusing, as we would have to continuously pass in props all the way down until we get to the component that needs it. This is referred to as prop drilling.
This often made our React Applications confusing, as it would be had to track down the where our props were coming from when debugging and inconvenient to tell each child component to pass down props that originated from multiple layers upward.
The React Context API allows us to define props at the highest level using a Provider and bring down the props we need from the provider by using the useContext hook on the specific component that needs those props. This prevents us from passing those props through components that don’t need them.
The first thing we want to do is create a basic react component in the root of our project called
// index.js
import React from 'react';
function ParentComponent(props) {
return (
<div>
<h1> Hi I'm the Parent Div </h1>
</div>
);
}
The next thing we want to do is create a child component in a different file
//child.js
import React from 'react';
function ChildComponent(props) {
return (
<div>
<h2> Hi I'm the Child Div </h2>
</div>
);
}
export default ChildComponent;
Lets import our child component into our parent component
// index.js
import React from 'react';
import Child from "./child";
function ParentComponent(props) {
return (
<div>
<h1> Hi I'm the Parent Div </h1>
<Child />
</div>
);
}
Lets create a grandchild component as well:
//grandchild.js
import React from 'react';
function GrandchildComponent(props){
return (
<div>
<h3> Hi I'm the GrandChild Div </h3>
</div>
);
}
export default GrandChildComponent;
Lets repeat the process we did for our parent and import our grandchild component into our child component
//child.js
import React from 'react';
import Grandchild from "./grandchild";
function ChildComponent() {
return (
<div>
<h2> Hi I'm the Child Div </h2>
<Grandchild />
</div>
);
}
Now we’re done building our React components, but now we want to pass data into our Grandchild component without it going to our Child component.
Two concepts React uses in its Context api are the Provider and the Consumer.
The Provider is the highest level component in the Context api and contains the values that we want to pass down.
The Consumer component lets you access values from our higher order Provider component.
Let’s create a new file called context.js. We’re putting it into a separate file because want our Parent component and Grandchild component to be able to access this component.
//context.js
import React from "react";
const Context = React.createContext();
export default Context;
Next we want to add the provider to our parent component, this will allow us to use our useContext hook in any of our components
Lets import our context component into our function
// index.js
import React from "react";
import Child from "./child";
import Context from "./context";
function ParentComponent(props) {
return (
<Context.Provider value={{ lesson: 'context for classes' }}>
<div>
<h1> Hi I'm the Parent Div </h1>
<Child />
</div>
</Context.Provider>
);
}
the value prop in our Context.Provider component will be the value we can pass into all of our parents descendant components.
The next step is to import the useContext hook from React
//grandchild.js
import React, {useContext} from "react";
import Context from "./context";
function GrandchildComponent(props) {
return (
<div>
<h3> Hi I'm the GrandChild Div </h3>
</div>
);
}
export default GrandchildComponent
We’re not done yet, we must define the value that useContext will be using from our Context. We will pull out the lesson variable from our Context. While it might seem like we’re getting this value from the Context file, remember that we passed in information into the Provider.
//grandchild.js
import React, {useContext} from "react";
import Context from "./context";
function GrandchildComponent(props) {
const {lesson} = useContext(Context);
return (
<div>
<h3> Hi I'm the GrandChild Div </h3>
</div>
);
}
export default GrandchildComponent;
Now we can access our lesson variable that we passed into the provider.
//grandchild.js
import React, {useContext} from "react";
import Context from "./context";
function GrandchildComponent(props) {
const {lesson} = useContext(Context);
return (
<div>
<h3> Hi I'm the GrandChild Div </h3>
{lesson}
</div>
);
}
export default GrandchildComponent;
We were able to pass in data originating from our parent component into our grandchild component without drilling our data down into our child component.