4

I was reading the Context > Parent-child coupling documentation of React. I was unable to get what parent-child coupling from the documentation. Typically this line :

By passing down the relevant info in the Menu component, each MenuItem can communicate back to the containing Menu component.

The code is:

<Menu>
  <MenuItem>aubergine</MenuItem>
  <MenuItem>butternut squash</MenuItem>
  <MenuItem>clementine</MenuItem>
</Menu>
JMM
  • 26,019
  • 3
  • 50
  • 55
Ajay Gaur
  • 5,140
  • 6
  • 38
  • 60
  • Basically, child can communicate with parent through callback that you can pass in the props of child. And parent communicates with children via props. You can concrete your question? – Sergii Shvager Mar 17 '16 at 13:47
  • @SergeyShvager The linked info is supposed to be saying something about context that differs from normal parent-child relationship via props. @ Ajay I had the [same question](https://discuss.reactjs.org/t/what-is-the-context-parent-child-coupling-example-about/3346). That section of the docs makes no sense to me. – JMM Mar 17 '16 at 15:08
  • @JMM I read your question during the search but could not find the solution. – Ajay Gaur Mar 17 '16 at 15:29
  • 1
    @Ajay That's funny. I'm surprised there's been no response to my post -- hopefully this will flush out some answers. – JMM Mar 17 '16 at 15:31

2 Answers2

2

As the article mentions, data flow in React is typically done by passing props from a parent to a child component. However, in some cases this prop sharing can become tedious, and in these cases, we'd use context.

The example in the document describes how continually threading a color prop would eventually become an annoyance, however in most cases you'd utilize context when the prop chain is much deeper than two or three levels. A better example might be the store in Redux.

For instance, those that use Redux, but don't implement react-redux, must access the store from the context. Now, let's say you have a very deeply nested component (grandchildren of grandchildren), and it needs access to the store - well, you can either:

  1. Pass store down via props. However, this means any intermediary component that doesn't need access to the store must have it as a prop nonetheless in order to pass it on to the child somewhere below it does that require it. Adding bulk and boilerplate.
  2. Attach the store to context at a high level component. As a result any child component that specifies a contextTypes within itself will have access to the context, and therefore the store. By doing so, we don't have to worry about injecting any intermediary component with unnecessary props, since we can just access the context.

Keep in mind, context is opt-in, therefore only components that explicitly specify contextTypes will have access to context, if one was so defined above it.

Using props

Parent (Passes props with a store property)
|
+-> props -> Child
           |
           +-> props -> Grandchild
                        |
                        +-> props -> Great-Grandchild 
                                     |
                                     +-> render() -> this.props.store.getState().message  

Using context

Parent (Defines childContextTypes with store property)
|
+ -> Child
     |
     + -> Grandchild
          |
          + ->  Great-Grandchild (Opts-in by defining contextTypes with a store property)
                |
                +-> render() -> this.context.store.getState().message  

UPDATE (with reference to this question posted by JMM):

What API is it referring to?

My understanding is that this refers to the ability for parent components to store functions on context, which can be accessed and invoked by child components, thereby creating a scoped API.

What does it mean: each MenuItem can communicate back to the containing Menu component.

Per the above, if a function were declared on context, and MenuItem opted-in via contextTypes to obtain the function, MenuItem could invoke it, thereby communicating with another component.

Community
  • 1
  • 1
lux
  • 8,315
  • 7
  • 36
  • 49
  • I understood this concept but I was specifically asking "*parent-child coupling*", as given in the example. The things which you wrote clears the thing about context and props but it is not what I want. – Ajay Gaur Mar 17 '16 at 17:32
  • @AjayGaur If you store functions on `context` and apply `context` to a parent component, you've essentially created an API for every child component. I'm sorry, but other than this I'm not sure what you're specifically requesting. – lux Mar 17 '16 at 17:35
  • Here the document says about how a child can communicate with the parent using contexts. As the line points out : "*each MenuItem can communicate back to the containing Menu component.*" – Ajay Gaur Mar 17 '16 at 17:38
  • @AjayGaur If you're looking at the first example in the document as a reference for `MenuItem` communicating back to `Menu`, it's not there. The first example only describes a scenario of when to use `context`. Unless you see anything different, I'm not noting any event emission or action communication from the child back to the parent in the color example. – lux Mar 17 '16 at 17:47
  • In the first example, there is nothing as parent-child coupling. But when you scroll, you would find the exact line which I mentioned in my question as well. – Ajay Gaur Mar 17 '16 at 18:22
  • and [this](https://discuss.reactjs.org/t/what-is-the-context-parent-child-coupling-example-about/3346) is the same question asked with no answer. – Ajay Gaur Mar 17 '16 at 18:23
  • @AjayGaur `What API is it referring to?` --> the ability for parent components to store functions on context, which can be accessed and invoked by child components. `What does it mean: each MenuItem can communicate back to the containing Menu component.` --> If a function were declared on context, and `MenuItem` opted-in via `contextTypes` to obtain the function, `MenuItem` could invoke it, thereby communicating with another component. – lux Mar 17 '16 at 18:39
  • Sigh... Thank you @lux. Sorry for wasting so much of your time just for the ambiguity in statement. It just cleared everything. Could you please edit the answer with this comment, so that answer can get the context of its parent. :P – Ajay Gaur Mar 17 '16 at 18:44
  • @AjayGaur No problem at all. Update was made - hopefully this clarifies things, but I agree, the documentation is very oddly worded and ambiguous. – lux Mar 17 '16 at 19:08
  • @lux I appreciate you taking a crack at this / my questions, but unfortunately it doesn't clear anything up for me -- the docs still make no sense to me. The answers you gave to my questions don't illuminate any fundamental difference between communicating functions via context instead of props. I understand that context allows more implicit passing of props through intermediate components, and the part of your answer using Redux as an example is good for illustrating that, but that doesn't seem related to what the "parent-child coupling" thing is talking about, with its one level of nesting. – JMM Mar 18 '16 at 13:34
  • @JMM I agree, I don't see how the child is linked back to the parent in that example provided in the doc, if at all; there's no event emission or any type of communication from the child back to the parent. This lead me to think this parent/child coupling section was rather referencing the fact that you *can* make APIs by effectively sharing functions on `context`, thereby tying the child back to the parent, but I assumed they just didn't provide an example of this. Any any rate, the extent of my knowledge of `context` has been reached. Hopefully, your post on Reactjs is answered. – lux Mar 18 '16 at 13:55
1

Consider the example:

ReactDOM.render(
  <Menu>
    <MenuItem>aubergine</MenuItem>
    <MenuItem>butternut squash</MenuItem>
    <MenuItem>clementine</MenuItem>
  </Menu>, mountNode
);

This can occur when Menu is implemented in the library code and doesn't have access to MenuItem, or MenuItems are shuffled with other arbitrary components within Menu.

Menu is the parent, but not the owner of the MenuItem, thus, it can't set the props on MenuItems directly. One way to work this around is to clone each child with new props. But if there are various types of nested components, some of them can receive redundant props.

Another way is to pass the data from Menu within the context and let arbitrary child components access it.

Community
  • 1
  • 1
Vitaly Kuznetsov
  • 1,515
  • 1
  • 16
  • 15