Consider the following React Component Tree:
<A>
<B>
<D>
<E/>
</D>
</B>
<C>
<D>
<E/>
</D>
</C>
</A>
A
, B
, C
, D
and E
are all components. Components don’t have a closing tag, but here I mean that A
renders B
and C
, then D
is rendered BY B
and C
components and so on.
I have a context (which is also a state variable) in A
, disabledChildCtx
initialized by a string "B". The context in its entire lifetime would just toggle between the values "B" and "C". This context here, is meant to disable some buttons in either B
or C
at a time according to value.
The component E
uses the context and looks something like:
const E = () => {
const ctxVal = useContext(disabledChildCtx);
return <button disabled = {/*.... some logic ....*/}></button>
}
E
just renders a button, which is either disabled or not depending upon some "logic". And the "logic" is, well:
- For the
E
which is descendant ofB
, if the context value is "B" (disabledChildCtx
), then the logic returns true, which disables the button inA -> B -> D -> E
. - For the
E
which is descendant ofC
, if the context value is "C", then the logic returns true, which disables the button inA -> C -> D -> E
.
The problem is both the E
s get same context, how can they decide uniquely if to render
or not a disabled button?
2
Answers
I figured out an answer to the problem. It would be better to create a context in its own file, say DisabledContext.js
Then, B and C can be used as context providers with a unique boolean value in their respective cases according to the props being passed by the parent A. Then, the boolean value, which is the context value now, can be used by E to directly enable or disable the button.
DisabledContext.js:
B.js
C.js
Now, no matter how many further common subchildren are there in , we can make the as a context consumer which simply uses the context value, irrespective of whose descendant it is.
You need to pass a prop down from B -> D -> E and C -> D -> E, so that E knows what its grandparent is. Then E can do something like
If you are hoping to be able to do this for any arbitrary component tree without passing props, so that E can always just magically figure out what its grandparent is, there’s not a straightforward way to do that. See is there any way to access the parent component instance in React?