The below question relates to the following sections in the React Context documentation:
Disclaimer: Apologies for all the background information below. It provides context and will hopefully be helpful to future visitors.
What We Know
- Link 1
- The (default) context value is set to
themes.dark
(an object that contains two properties:foreground
andbackground
) - The default value is only ever used if there are no
Providers
above theConsumer
in the component tree - In this case, there is a
Provider
present in the top-level component (App
) - This
Provider
(App
), passes down its ownstate
as the context value - It is smart to keep the values provided by a
Provider
equal in structure and type to the default context value (avoidsConsumers
getting confused) - Thus,
state
in the top-level component (App
) holds an object of the same format as the default context value:themes.light
- Conclusion from the above: When a
Consumer
reads the context, it readsApp
's state - In other words, we are here using context to pass a parent (
App
)state
deep down in the component tree, without having to pass it through every component in the middle - When state in the top-level component (
App
) changes, it re-renders and a new value for state is provided to theConsumer
- This way, the
Consumer
reads the parent'sstate
, via context - ...
- Moving on, we see in link 1 that a function to set
state
(toggleTheme
) is passed down the component tree as a normalprop
- Thus, in link 1,
context
only contains an object that readsstate
- We are able to set state in the
Consumer
by passing thesetState
function as a normalprop
from theProvider
's child, down through all the intermediate components, and in to theConsumer
- Setting the
state
in the top-level component (App
), leads to a re-render of itself, which leads to a re-render of theProvider
, which then passes the newApp
state
value down to itsConsumer
via context - As such, the
Consumer
always knowsApp
's state, via context - In conclusion, the flow is:
- Parent's
state
is provided as context value to childConsumer
(s) - Parent's
state
is updated by some child - Parent re-renders
Provider
sees that context value (App
'sstate
) has changed, and re-renders all itsConsumer
s with the new value
- Parent's
- The (default) context value is set to
- Link 2
- In link 2, we set
state
in theConsumer
, by passing thesetState
function within the context - This differs from link 1, where we relied on a normal
prop
to setstate
- In link 2, we set
Questions
We know from the docs that:
Every Context object comes with a Provider React component that allows consuming components to subscribe to context changes....
All consumers that are descendants of a Provider will re-render whenever the Provider’s value prop changes.
- Let's assume we use a normal variable in
App
as the context value. We know from the above quote that changing it leads to theProvider
re-rendering. Why then, do we bother usingstate
as the context value? What is the benefit of that, vs. just using any normal variable inApp
? - Both the two approaches above allow us to update
state
. Why is link 2 incorporating the function to updatestate
withinstate
itself? Could we not just have it as a separatesetState
function, which is passed to theConsumer
via context in an object that has two properties (one isstate
and the other is the standalone function to updatestate
)?