Context is React’s way of handling shared data between multiple components.
When working with two connected components in a React application, the easiest way to share data between them is through props. For example, if the child component needs data from the parent component, it can receive that data via props.
const HomePage = ({ person }) => { // use person data from props here return ( <div> {person.firstName} {person.lastName} </div> ) } const ProfilePage = () => { const user = { firstName: 'Jane', lastName: 'Doe' } return ( // call HomePage component and pass person as it's props <HomePage person={user}/> ) }
However, if there are more than two components at different nesting levels, it becomes a more difficult task to share data between disconnected components.
For instance, if we want to share data between a top-level component and a third-level component, we’ll have to pass the data as a prop to the second-level component even if we won’t need the data there.
This is so that the second-level component can then pass the data to the third-level component:
const HomePage = ({ person }) => { // HomePage receives "person" as a prop for the // SettingsPage return ( <SettingsPage person={person} /> ) } const SettingsPage = ({ person }) => { return ( <div> {person.firstName} {person.lastName} </div> ) } const ProfilePage = () => { const user = { firstName: 'Jane', lastName: 'Doe' } return ( // Even though HomePage does not need the person prop, it still // has to be called with it for the SettingsPage component <HomePage person={user}/> ) }
Context solves this problem by providing a global state that every component can easily access without the need to pass data via props from a parent through multiple child components.
React.createContext
The createContext
method is used to create a Context object to which components can subscribe. These components are able to get the context value from the closest matching Provider above them in the tree.
const NewContext = React.createContext({ color: 'black' });
Components are usually wrapped in a Provider in order to get their context value. However, when there’s no matching Provider above a component in the tree, the component will get its context from the default argument { color: 'black' }
in the createContext
method. This is especially useful when testing components in isolation.
Context.Provider
The React.createContext
method will return a Provider component when it is called. Providers are React components from Context objects that allow other components to access those context values and subscribe to their changes.
const { Provider } = NewContext;
The Provider component accepts a value
prop, which can then be accessed by its consuming child components. A Provider can have multiple child components or consumers.
<Provider value={{color: 'blue'}}> {children} </Provider>
Components will use the default context value from the createContext
method when they have no matching parent Provider. However, once a Provider is available, even if its value
prop is undefined
, its child components or consumers will use its value.
Whenever a Provider’s value
prop changes, its subscribed consumers will re-render.
Context.Consumer
The React.createContext
method also returns a consumer component when it is called. Consumers are React components that subscribe to context changes from Providers.
const { Consumer } = NewContext;
Context.Consumer
makes subscribing to a context within a function component possible.
<Consumer> {value => <span>{value}</span>}} </Consumer>
Context.displayName
Context.displayName
is a string property from the React.createContext
method call. The React DevTools will use whatever displayName
is given to a context to determine what to display for that context.
NewContext.displayName = 'NameOfContext'
When NewContext
is viewed in the React DevTools, its name should appear as NameOfContext
:
<NewContext.Provider> // Shows up as NameOfContext.Provider <NewContext.Consumer> // Shows up as NameOfContext.Consumer
Class.contextType
The Class.contextType
property allows a component to consume the nearest value of a Context object that has been assigned to it.
class newComponent extends React.Component { render() { // use the context value assigned to the class.ContextType property {this.context} } } newComponent.contextType = NewContext;
Note that the class.contextType
property will allow you to subscribe to only one context. In the above example, this.context
was referenced in the render()
method. It can also be referenced in all the other lifecycle methods, including componentDidMount()
, componentDidUpdate()
, and componentWillUnmount()
.
It’s important to note that with Context, components lose much of their independence. Because of this, it’s more difficult to reuse components that depend on Context. With this disadvantage, it might be easier to use component composition at times, especially when your only reason for using Context is to avoid prop drilling.
Context also uses reference identity to determine when to re-render. Thus, there are some cases in which unintentional renders could be triggered in consumers when a Provider’s parent re-renders. Here’s an example:
class newComponent extends React.Component { render() { return ( <NewContext.Provider value={{color: 'blue'}}> <ProfilePage /> </NewContext.Provider> ) } }
In the above snippet, there will always be a new object for value
, and therefore, all the consumers will re-render every time the Provider re-renders. To get around this, you’ll have to put the value in the parent’s state and reference it in the Provider component:
class newComponent extends React.Component { constructor(props) { super(props) this.state = { value: { color: 'blue' } } } render() { return ( <NewContext.Provider value={{this.state.value}}> <ProfilePage /> </NewContext.Provider> ) } }
Here’s a live demo that illustrates how to handle dynamic values with Context.
Install LogRocket via npm or script tag. LogRocket.init()
must be called client-side, not
server-side
$ npm i --save logrocket // Code: import LogRocket from 'logrocket'; LogRocket.init('app/id');
// Add to your HTML: <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script> <script>window.LogRocket && window.LogRocket.init('app/id');</script>
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowThe useReducer React Hook is a good alternative to tools like Redux, Recoil, or MobX.
Node.js v22.5.0 introduced a native SQLite module, which is is similar to what other JavaScript runtimes like Deno and Bun already have.
Understanding and supporting pinch, text, and browser zoom significantly enhances the user experience. Let’s explore a few ways to do so.
Playwright is a popular framework for automating and testing web applications across multiple browsers in JavaScript, Python, Java, and C#. […]
3 Replies to "React Reference Guide: Context API"
Thx,
that was supper helpful 🙂
You’re welcome, Montassar!
thanks a lot to update us