Hello, our team is writing a framework of React' system, and now we are facing a problem: To judge if an instance of a component is a child of another( It may in deep layer of the parent instance ). We think there should be a function to resolve these problems, but we cound not find it out.
We need your help.
Thanks a lot.
I usually just do that type of comparison by tagging things with IDs and using the DOM .contains() API. A little inelegant, but I'm not aware of non-test tooling for the use case.
Could you explain your use case in more detail?
@yaycmyk Yeah, we finally find a way that may probably effect, it's the _owner property , we are trying on it.
Please don't rely on _owner, it's an implementation detail and might change behavior in future releases. Generally anything with underscores that isn't documented in public API docs isn't a public API ;-)
@gaearon Hello. We defined a component (instance of React.Component), and it's used merging with other components or HTML tag. Such as(named Group):
<div>
<Group key={1} name="group1">
<div>
<Group/>
<div>
<Group name="group2"/>
</div>
</div>
</Group>
<Group key={2}>
<Department/>
</Group>
</div>
class Department extends React.Component {
render() {
return (
<div>
<Group key={1} name="group3"/>
<Group key={2}/>
</div>
)
}
}
We want to find if the Group instance named 'group3' (or 'group2') is a chind of that named 'group1' (Obviously, 'group2' is while 'group3' isnot) .
@gaearon Yeah, thanks for your reply, but we couldn't find out another way to resolve these problems.
@vifird have you seen the Context feature?
class Group extends Component {
getChildContext() {
return { group: this.props.name };
}
render() {
const parentGroup = this.context.group; // it will be undefined in the roots
console.log('parentGroup', parentGroup);
return (
<div className="group">
{this.props.children}
</div>
);
}
}
Group.contextTypes = {
group: PropTypes.string
};
Group.childContextTypes = {
group: PropTypes.string
};
@eliseumds
Thanks for your advice. It's really a good idea for this scene.
@yaycmyk @gaearon @eliseumds
Thanks for all of you. We found a way out finally. It's used by _owner and props.children. It's a common solution for these problems. and it's not resolved by open APIs, but it doesn't matter for us.
Here we share our code (the reactContains is the main function):
/**
* judg if parentComponent contains childComponent
*/
export function reactContains(parentComponent, childComponent) {
if(!parentComponent || !childComponent
|| !(parentComponent instanceof React.Component)
|| !(childComponent instanceof React.Component)) {
return false
}
const parentSelf = parentComponent._reactInternalInstance
const childSelf = childComponent._reactInternalInstance
const parentOwner = parentSelf._currentElement._owner
let childOwner = childSelf._currentElement._owner
while(childOwner
&& childOwner !== parentSelf
&& childOwner !== parentOwner) {
childOwner = childOwner._currentElement._owner
}
if(!childOwner) {
return false
}
if(childOwner === parentSelf) {
return true
}
if(childOwner === parentOwner) {
return isChild(parentSelf._currentElement, childSelf._currentElement)
}
}
/**
* judge if childElement is a child of parentElement
*/
export const isChild = (parentElement, childElement)=> {
if(!parentElement || !childElement) {
return false
}
if(parentElement === childElement) {
return true
}
if(!parentElement.props
|| !parentElement.props.children
|| (typeof parentElement.props.children === 'string')) {
return false
}
let children = parentElement.props.children instanceof Array ? parentElement.props.children : [ parentElement.props.children ]
// React.Children.toArray(parentElement.props.children)
for(let i=0; i<children.length; i++) {
if(React.isValidElement(children[i])
&& isChild(children[i], childElement)) {
return true
}
}
return false
}
Note that this code is extremely fragile and can (and likely will) break in any patch version of React without warning. It will also be very confusing to anyone who used React but haven't seen your project so please consider the longer term maintainability of this.
Most helpful comment
Note that this code is extremely fragile and can (and likely will) break in any patch version of React without warning. It will also be very confusing to anyone who used React but haven't seen your project so please consider the longer term maintainability of this.