React Context — Why and how
Being React developers, we all know that React has unidirectional data flow.
React Context — Why and How
Being React developers, we all know that React has unidirectional data flow. We create high level components, where we fetch the data, and then we nest all other components inside passing the data down using props. So the data is flowing in one direction only, from high level component to its child components and then these child component might pass the data on to their children if needed.
Now there are sometimes when we want a piece of data in a deeply nested child component, we will need to pass it all the way from the component where it is available, down to the actual child component where it is required, passing through many other components in between. This is a problem, because these other components don’t need this data.
React came up with a solution to this problem which is called Context
.
Context provides a way to pass data through the component tree without having to pass props down manually at every level.
Let’s take an example for this.
const AComponent = ({message}) =>{
return <div><BComponent /></div>
}const BComponent = ({message}) =>{
//we want to display messageForB here.
return <div>{message}</div>
}export default function App() {
const [message, setMessage] = useState('Hello world!');
return (
<div className="App">
<AComponent message={message} />
</div>
);
}
As you can see in the above example we have a piece of data message
which we want to display in BComponent
only. It’s not needed in AComponent
but still because of unidirectional data flow we have to pass it through AComponent
.
This becomes a problem in large applications, where we have some global data that is required at various places in the application, because of this issue we have to pass it through the props each time, modifying the props for lots of other components, which don’t even use this data.
So how does the Context
solve this issue. Let’s take a look.
Let’s first create a context object:
const MessageContext = React.createContext('A default message!');
This statement creates a context object, with a default value. Now this context object comes with a Provider component. Provider component allows the components which use this data, to subscribe for the changes in the context data.
<MessageContext.Provider value={"Hello world!"}>
Now all the components which are nested under this provider component can access the data provided by this provider, by doing following
const BComponent = () =>{
const message = useContext(MessageContext);
return (<div> B Component : {message}</div>);
}
Thats it!. You now have the data available in your child component, without needing to pass it through the props.
Your whole code should look like this.
import React, { useState, useContext } from "react";const AComponent = () =>{
return <BComponent />
}const BComponent = () =>{
const message = useContext(MessageContext);
return (<div> B Component : {message}</div>);
}const MessageContext = React.createContext('A default message');
export default function App() {
const [message, setMessage] = useState('Hello world!');
return (
<div className="App">
<MessageContext.Provider value={message}>
<AComponent />
</MessageContext.Provider>
</div>
);
}
This is cool. Isn’t it ? But React suggests to avoid the use of Context frequently. Because as per React Docs it makes the component reuse difficult.
Context is primarily used when some data needs to be accessible by many components at different nesting levels. Apply it sparingly because it makes component reuse more difficult.
You can read more about Context in react documentation here.