Instantly share code, notes, and snippets.

Embed
What would you like to do?
Parent vs. Owner Context

If you've reached this page, it's probably because your "parent-based and owner-based contexts differ".

As we've been iterating on React's "context" feature, we've discovered that the parent-based relationship is more useful than the owner-based relationship, so we're migrating to use a parent-based hierarchy.

In short, the owner of a component is whomever creates the component, while the parent of a component is whomever would be the containing ancestor in the DOM hierarchy. To learn more about the owner relationship, see the docs here: http://facebook.github.io/react/docs/multiple-components.html

In many cases, the owner and the parent are the same node, in which case, no further action is necessary. However, if your owner and your parent differ, you should ensure that the context variables you're using aren't going to break when we switch from owner-based contexts to parent-based contexts. If you're seeing the warning, your component may not be ready for the switch.

NOTE: semantically-equal context variables... In some rare cases, you might have a getChildContext function which is not idempotent or which returns objects using value semantics. For instance, if your getChildContext() returns a random number, you might get a warning like:

Warning: owner-based and parent-based contexts differ (values: '0.91666' vs '0.37677')...

Such cases are not necessarily a bug, but are probably bad practice. Our recommendation is that you fix these situations to ensure getChildContext returns the same value (triple equals equality) for a particular set of inputs (props/context). That said, as long as your context variables are semantically equivalent, you should be able to update to 0.14 without things breaking.

@glenjamin

This comment has been minimized.

glenjamin commented May 28, 2015

@jimfb The short-url in the warning (http://fb.me/react-context-by-parent) is still pointing at your old username - so is a dead link at the mo :(

@StoneCypher

This comment has been minimized.

StoneCypher commented Jun 15, 2015

this doesn't really explain how to fix it though

@StoneCypher

This comment has been minimized.

StoneCypher commented Jun 15, 2015

it's a real shame this is being done; this makes contexts broken around reusable controls

@StoneCypher

This comment has been minimized.

StoneCypher commented Jun 15, 2015

i may have misunderstood; possibly ignore the above.

are contexts not present in an intermediate pushed downwards on their own?

@jedwards1211

This comment has been minimized.

jedwards1211 commented Jun 15, 2015

I had been assuming that if a component defines the proper contextTypes, it can get the corresponding context variables set by an ancestor even 100 levels up, even if none if the components in between define any contextTypes. Am I wrong?

@Cellule

This comment has been minimized.

Cellule commented Jun 16, 2015

I really don't understand how owner-based context works, it seems like no matter what I do the parent context is fine, but the owner context is undefined.
The weird part is that it works for 2-3 levels of children then it stops working.
My code is ready for React 0.14, but I'll have to live with fallback solutions in the mean time.

@admmasters

This comment has been minimized.

admmasters commented Jun 21, 2015

Frankly I see this as a bug in React and the way it handles context - as this is undocumented at this stage, fair enough - however the behaviour I am seeing is as follows:

TopLevelPage has a context containing the object "branding".
TopLevelPage has a ListView component (React-Native) - which from a high level can be used to render collections.
ListView has a callback which renders components, in this instance Card.
At this stage within the closure we have the correct context and you can see the property branding.
Once the Card component has been created - we lose context and branding becomes undefined - for the sanity of the api I believe the child component should inherit the context within which it is created.

@admmasters

This comment has been minimized.

admmasters commented Jun 21, 2015

@jedwards1211 this was pretty much my understanding. The behaviour I'm seeing may be related to React Native's ListView component and the way it renders, but at this stage it seems like contexts are still a bit dangerous to use in a "real" project.

@gnapse

This comment has been minimized.

gnapse commented Jun 28, 2015

I'm not sure if this the right place to bring this up, but here it goes:

Take a look at this jsfiddle: https://jsfiddle.net/hg08LLL0/2/
It gives the warning in the console that leads to this page, and I really do not understand why.

In that example, the data I'm passing down to TodoItem as props (not as context) is a map from the immutable-js library. Now, if I modify it to be regular js objects, the error goes away. Here's another jsfiddle with the data being passed as regular objects: https://jsfiddle.net/mzugp1yd/2/

So why the thing I'm passing in the props is affecting the triggering or not of this error? Note that the code related to contexts is exactly the same in both examples. The only thing that changes is that the props are immutable objects in one, and regular objects in the other.

@BurntCaramel

This comment has been minimized.

BurntCaramel commented Jul 1, 2015

Is getChildContext() allowed to return a value based on state, which gets changed with setState()?

@jorge-pascual

This comment has been minimized.

jorge-pascual commented Aug 3, 2015

@gnapse I have been playing with your code and I think the problem isn't with Inmutable. I think the problem is around the way the child components are made.

I've removed the loop and put directly the item list and the warning has gone away... you can see it here:
https://jsfiddle.net/b4n3wqz8/1/

So, I think the problem is located with the children own (or parent, I'm not really sure). When child component creation is made directly inside the render() it works well because the own and parent are well assigned to children.

However, when children are made inside a function that "lost" (or something) the render() context, the own or the parent(I'm not sure which one) is lost. So, the own.context or parent.context is lost also and the warning is triggered because one of them is undefined.

This is my approach to the problem... however, I don't know why own or parent is lost.

@KamilSzot

This comment has been minimized.

KamilSzot commented Aug 5, 2015

Is there a way to get parent context (not owner context) in the child in current version of react?

@tomprogers

This comment has been minimized.

tomprogers commented Aug 26, 2015

Alright, so given that my owner and parent contexts have different content (i.e.: the parent context is empty and the owner context has goodies), how am I supposed to manage the parent context? The parent isn't a genuine React component -- it's just some div or span or whatever. It's going to be a problem if I'm expected to promote into full-fledged custom components each of the ancestors between the owner and the sub-component. But I don't see an alternative.

I.e.: what does it look like to "ensure that the context variables you're using aren't going to break when we switch from owner-based contexts to parent-based contexts" ?

As far as I can tell, this gist is long on diagnosis and short on prescription. Both are needed.

@hellogerard

This comment has been minimized.

hellogerard commented Sep 4, 2015

I am also seeing this error when trying to pass context to dynamic children. So if I have a component like:

render: function() {
  <div>
    {this.props.dynamicComponentFromParent}
  </div>
}

Whatever component that gets passed in gets undefineds in its context. This makes sense since the owner is the parent component, but the parent is the component doing the render. Not sure what to do about it.

@L8D

This comment has been minimized.

L8D commented Sep 8, 2015

@hellogerard you're getting that issue because you're passing in a component (like dynamicComponentFromParent={Foo}) instead of a react element (like dynamicComponentFromParent={<Foo/>})

@ghost

This comment has been minimized.

ghost commented Mar 22, 2016

What is meant by reparenting in reactjs .. An example would be great.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment