I have a ponent structure as follows:
const Parent = (props) => {
return <div>{props.children}</div>;
};
const Child1 = (props) => {
return <h2>child 1</h2>;
};
const Child2 = (props) => {
return <h2>child 2</h2>;
};
And I create an instance as follows:
const node = <Parent>
<Child1 />
<Child2 />
</Parent>
Now, as I am exposing this to outside world, users might forget to pass <Child1 />
or <Child2 />
in the parent. I want to detect this in the parent and then render something else based on if <Child2 />
was passed or not.
What I tried: I have made use of the context API to have some munication between parent and child. I am looking for something simpler than this.
Something like this: .js#L69
I have a ponent structure as follows:
const Parent = (props) => {
return <div>{props.children}</div>;
};
const Child1 = (props) => {
return <h2>child 1</h2>;
};
const Child2 = (props) => {
return <h2>child 2</h2>;
};
And I create an instance as follows:
const node = <Parent>
<Child1 />
<Child2 />
</Parent>
Now, as I am exposing this to outside world, users might forget to pass <Child1 />
or <Child2 />
in the parent. I want to detect this in the parent and then render something else based on if <Child2 />
was passed or not.
What I tried: I have made use of the context API to have some munication between parent and child. I am looking for something simpler than this.
Something like this: https://github./mui-org/material-ui/blob/next/packages/mui-lab/src/TimelineItem/TimelineItem.js#L69
children
? It would be very tricky to check it like that, whilst having a prop of renderChildOne
or something like that would make it way easier to check
– Ron B.
Commented
Sep 8, 2021 at 13:47
Autoplete
ponent expects a prop called renderInput
, instead of checking whether one of the children contains an input. So that's definitely the better pattern.
– Ron B.
Commented
Sep 8, 2021 at 13:55
If only the number of children is important then:
const count = React.Children.count(children);
To check specific ponents:
let child1Exists = false;
let child2Exists = false;
for (const key in props.children){
const ponentName = props.children[key].type.name
switch(ponentName){
"Child1":
child1Exists = true;
break;
"Child2":
child2Exists = true;
break;
default: break;
}
}
if(child1exists && child2Exists){
// All good!
}
Its better to make this logic posable using higher order ponents.
This is the HOC. you can reuse it anywhere.
function withExpectedChildren(Component, expectedChildren = []) {
return function Wrapped(props) {
const hasAllExpectedChildren = expectedChildren.every((expectedChild) =>
[props.children].flat().find((child) => child.type === expectedChild)
);
return hasAllExpectedChildren ? <Component {...props} /> : props.fallback;
};
}
Wrap Parent ponent with the above HOC
const WrappedParent = withExpectedChildren(
Parent,
[Child1, Child2]
);
Render the posed ponent. It renders fallback, if any child misses.
<WrappedParent fallback={<h2>you missed a child</h2>}>
<Child1 />
<Child2 />
</WrappedParent>
You can see the working fiddle at https://jsfiddle/nqbL8g1m/
This is the idea, you shall modify it for your requirements