5

Is there a way in ReactJS for a component to find out who it's parent is?

EDIT 1: Regardless of the merits of doing this, is there a way?

I haven't found a React way to do this - from what I can see, the idea is to pass callbacks down to the child from the parent, and the child calls the callback - unaware of the fact that the callback is actually on the parent.

I've tried setting an "owner" property, and that idea seems to work, but I wonder what's the best approach?

e.g.

<Parent>
  <Child owner={this}/>
</Parent>

Then in the child component, I can do owner.method, and it seems to work fine. I know this isn't a true parent/child relationship, but is the closest I've found in my tests.

Some may say that callbacks are a cleaner way of doing this, but the parent/child relationship for some things (e.g. RadioButtonGroup and RadioButton) seems natural and would benefit from knowing this relationship, in my opinion.

EDIT 2: So it's not possible?

The thing that I don't like about the idea that it's not supported is that HTML can be marked up with zero javascript - and it has implied, default functionality - some elements are required to have parents - they are defined as children of other elements (e.g. ul and li). This can't happen in JSX because if there is interaction between the elements - there has to be javascript events that bind the components together - every single time you use them. Designers can't simply write HTML like syntax - Someone has to step in and put some javascript bindings in there - which then makes the maintenance harder. I think the idea makes sense for overriding default behavior, but default behaviors should be supported. And defaults would require knowing either your parent, or who your owner is.

Community
  • 1
  • 1
Brad Parks
  • 66,836
  • 64
  • 257
  • 336

2 Answers2

4

There are a number of benefits to not doing this, the main two are: reusability and encapsulation.

TL;DR you probably don't want to do this ever.

Let's say our RadioButton has this public interface:

<RadioButton active={true} onSelect={function(event){}}>text</RadioButton>

We could construct another component called SuperRadioButton, which might have a different way of presenting itself, but still have the same public api as RadioButton, so it's a valid child of RadioButtonGroup.

If we're accessing the parent, then the parent's internals become part of the public api of these components, and we need to be much more careful with how we change our code, because a change in any of these components could cause the entire application to break.

Brigand
  • 84,529
  • 20
  • 165
  • 173
  • hey... thanks for the feedback! I do understand the pluses/minuses of this, and am willing to build custom composites for each time I want to do this type of thing, which alleviates the main concern with this - so I think the original question still stands - is there a clean react way of getting a components parent? – Brad Parks Jun 25 '14 at 02:40
  • There isn't a better way than what you already have currently. There's some talk about exposing an owner property, but I'm not sure if it's going to happen. – Brigand Jun 25 '14 at 06:02
  • 1
    @BradParks I agree with FakeRain. If you find yourself in a situation where you need to access the parent component, you are most likely using an anti-pattern or need to improve your application design. Exposing callbacks as props is generally the way to interact between components. – David Hellsing Jun 25 '14 at 08:51
  • "There's some talk about exposing an owner property." I haven't heard any talk of this. – Sophie Alpert Jun 25 '14 at 18:23
  • Maybe I'm thinking of something else, well nevermind :-) – Brigand Jun 25 '14 at 18:53
  • 2
    So.... I guess there's no way to do it then, correct ;-) Other than what I'm already doing? – Brad Parks Jun 25 '14 at 20:39
  • Well the whole "thinking in react" approach focuses on building composites - and top level components owning state... And given that quite often child components would be rendered dynamically, I think there's some merit to this approach - it would force all parent components to have the same contract, without all the busy work of callbacks.... Care would have to be taken, but I can see and understand the use case... – TheWestIsThe... Jun 26 '14 at 12:31
  • The whole point of react is top down. If you find yourself needing to get the parent, you're doing it wrong. – Mike Driver Jun 28 '14 at 02:52
1

Callbacks. Owner properties. Passing events out to be caught by the root in the tree. Passing the root down through contexts.

There are ways, yes, but they're contrary to the conceptual model of react, which is to be explicitly top down at all times. The short version is "you can, but don't."

The fundamental problem is that you don't want a child mutating outside its parent's knowledge.

That means that the sole exception to this is the root of the component tree, so it's semi-legit to pass a member of that control downwards in props or contexts then to "pass things up" by telling the root, which may then repaint itself.

The application layer Flux does something not terribly dissimilar to this, but passes things outside of the component heirarchy entirely to a dataStore, which broadcasts things back in with events.

John Haugeland
  • 9,230
  • 3
  • 37
  • 40
  • thanks for the feedback - i don't want my children to mutate outside outside of it's parents knowledge - i simply want my child to be able to notify it's parent that it should mutate it's state - ie the parents state - which would then pass down to the child. I can do this with callbacks of course, but then my HTML like JSX is HTML with javascript which is less HTML like... If my child could call `parent.selectChild(childIndex)` then I could have automatic "reactions" – Brad Parks Jul 05 '14 at 01:27