Prerequisite
This article assumes you have a basic understanding of the React.js framework.
What is Context?
Context is the React solution for creating global data. This makes it consumable from any component, no matter how deep it is.
The basic example of using Context. Assume you need to use the theme
state. And it's defined in the App
component, from the GreatGrandChild
component. To do that, you'll pass the state through each component in the components tree until you reach the GreatGrandChild
component.
Context saves you that burden of prop drilling states and methods. Create a separate context file holding the state and its methods.
Creating A Context
Creating a Context has 3 steps: creating, providing, and consuming. To create a Context create a file under the src directory of the project. It'll be named after the context's name such as themeContext.js
. Then use createContext
API which creates the Context object. Finally, export the context object.
In src/themeContext.js file
Providing A Context
Each context object has a Provider
component. The Provider
component is used to provide the context to any of its children components. A Provider
component has a value
object prop which holds the context value and the updater method.
Think of the Provider component as the house of the context. The components inside that house have access to it, so they can consume it and listen to its updates. So, whenever there is a change, all the consumer components are re-rendered.
To make things easier, create the Provider
component inside the context file.
In src/themeContext.js file
Now that we have the Provider
component, let's use it for providing the context. Import the ThemeContextProvider
component from inside App.js. Then, pass the children components to it.
In src/App.js
Consuming A Context
You have to tell React which component is dependent on the context. So that not every component is re-rendered on changes.
Note: There can be more than one provider in the components tree. The consumer components match the value of the nearest parent provider. If there are no providers above the consumer, it will receive the default value from the context file.
From class components
To consume the context object from a class-based component, assign the context object to a static contextType
and you're good to go. This way you can destructure the theme
value and its updater from anywhere inside a component class.
In src/components/DeepLevelComponent.jsx
Another way to consume a context from class-based components is to use the themeContext.Consumer
component but it's more of a legacy way. The trade-off here is that you can't use the Context value anywhere but inside the render method. On contrary, contextType
allows you to use the context in any lifecycle method besides the render method.
From functional components
It's not very different. We'll use React hook useContext
. It does the same job as static contextType
.
In src/components/ChildComponent.jsx
Summary
Using context is easy and helpful. It could be what you're looking for, but be careful not to miss use it.
That's it. I hope I clarified things enough. Feel free to write your thoughts in the comment section below.
Top comments (3)
Very good man!
When creating the provider, why the additional level of indirection on
setTheme
?If you mean the "updateTheme" method, it's meant to be an example of a method that can do more than just updating the theme state. For example, it could be a method that triggers a fetch request, in which updating the state is not a direct step.