The variables or values defined in context are available to any component that tries to destructure those values. However, if you have any setters that change those defined values, only the children that are passed to the Provider will get the updated values.
For instance, if we create a context myContext and define name and age, we have to then set up a provider that will provide it's children that information to consume.
const myContext = createContext({
name: 'Bob',
age: 35
});
Now, we can use a Provider to pass that data down to children.
function HelloWorld() {
const { Provider } = myContext;
const [age, setAge] = useState(35)
const [name, setName] = useState('Bob')
return (
<Provider value={{ name, age }}>
<Profile />
</Provider>
)
}
name and age are the values we want to expose to our children, in this case we just have one child Profile. Now we can access name and age in Profile by destructuring them from our context.
function Profile(){
const { name, age } = useContext(myContext)
return (
<ul>
<li>{name}</li>
<li>{age}</li>
</ul>
)
}
But let's say somewhere else in our project we have component called Foo and we want to access name.
function Foo() {
const { name } = useContext(myContext) // you will only receive the default values defined in context
return <p>{name}</p>
}
This will return the default 'Bob' defined in myContext. You may think, what was the point of that?
If we update our HelloWorld component to actually update the name and age onMount, Foo will still show Bob.
function HelloWorld() {
const { Provider } = myContext;
const [age, setAge] = useState("");
const [name, setName] = useState("");
useEffect(() => {
setAge(40);
setName("Bill");
}, []);
return (
<Provider value={{ name, age }}>
<Profile />
</Provider>
);
}
function Profile() {
return (
<ul>
<li>{name}</li> // returns Bill
<li>{age}</li> // returns 40
</ul>
)
}
function Foo() {
return (
<p>{name}</p> // returns Bob
)
}
This is great when you have isolated features or components that need to pass around data and setters instead of prop drilling. You can have a component consume multiple contexts and you can have as many contexts as you want as long as they make sense. If you are passing a prop down just once, does not make sense to use context. If you have more complex passing of props, context may be worth it.