Context makes it easy to pass data from a component to any of its child components. The child component can be of any level.
Passing Data Without Props
Here we have four components. It is named as L1
, L2
, L3
, L4
to show the level of component in which it is used.
export default function L1() {
return (
<div>
<h4>Level 1</h4>
<L2 />
</div>
);
}
function L2() {
return (
<div>
<h4>Level 2</h4>
<L3 />
</div>
);
}
function L3() {
return (
<div>
<h4>Level 3</h4>
<L4 />
</div>
);
}
function L4() {
return (
<div>
<h4>Level 4</h4>
</div>
);
}
We need to now pass some data from L1
to L4
. How to do it? The only way is like water flowing down in steps. The data needs to be passed from L1
to L2
through props, then from L2
to L3
and finally, L3
to L4
. Here is how it looks like:
export default function L1() {
const name = "Joby";
return (
<div>
<h4>Level 1</h4>
<L2 name={name} />
</div>
);
}
function L2(props) {
return (
<div>
<h4>Level 2</h4>
<L3 name={props.name} />
</div>
);
}
function L3(props) {
return (
<div>
<h4>Level 3</h4>
<L4 name={props.name} />
</div>
);
}
function L4(props) {
return (
<div>
<h4>Level 4</h4>
<h3>Name is {props.name}</h3>
</div>
);
}
Above code produces below output:

You can play with this code online at CodeSandbox.
Passing Data Using Context
Context acts like a global space. Once we create and connect a context to a component, the component and all its children have access to the context to fetch the data. It will be more clear with an example.
Create Context
First step is to create a context object. For that, import createContext
from React.
import { createContext } from "react";
Next, we create a context object.
const NameContext = createContext("John");
Here, "John"
is the default value of the context. We can override the value when using the context object.
Provide Context
We need to now provide the context to the L1
component. For that, wrap the L1
component inside NameContext.provider
. Also, we can pass a value
attribute. This value is then available to all child components.
export default function L1() {
const name = "Joby";
return (
<NameContext.Provider value={name}>
<div>
<h4>Level 1</h4>
<L2 name={name} />
</div>
</NameContext.Provider>
);
}
As we can see above, we are passing a string "Joby"
as value. This new value override the default "John"
value.
Read Context Value
In the earlier section, we provided the value in L1
component. Next, we are trying to take the value in L4
component. For that, we can use useContext()
hook.
function L4() {
const name = useContext(NameContext);
return (
<div>
<h4>Level 4</h4>
<h3>Name is {name}</h3>
</div>
);
}
useContext()
accepts a context object and returns the value it stores. This is how useContext()
shares data across components.
useContext() Usage
If in our application, we need some data to be available globally, it is good to use Context. One application can be site theme. Based on Light or Dark theme, all the components needs to update their styles.
Context vs Redux
Latest Redux internally uses Context API. It is suggested to use either Redux or Context. Using both at the same time is not suggested.