React get Children recursively
React get Children recursively
by jonahe
HTML
<div id="app"></div>
CSS
fieldset {
margin: 0px 0px 10px 0px;
border: 1px solid teal;
padding: 20px;
}
div.form-element {
border: 1px solid teal;
padding: 20px;
}
React
const getChildrenRecursively = (soFar, parent) => {
if(typeof parent === "string") return soFar.concat(parent);
const children = Array.isArray(parent.props.children) ?
parent.props.children :
React.Children.toArray(parent.props.children);
const childCount = children.length;
if(childCount <= 0) {
return soFar.concat(parent);
} else {
return soFar.concat([parent], children.flatMap(child => getChildrenRecursively([], child)));
}
}
const MyInput = ({label} ) => <input placeholder={label} ></input>;
const MyComp = ({children}) => {
const childArr = React.Children.toArray(children);
// get all children in hierarcy
const flattenedChildren = childArr.reduce(getChildrenRecursively, []);
const numberOfInputs = flattenedChildren
.filter(child => child.type && child.type.name === "MyInput").length;
const Wrapper = numberOfInputs > 1 ? 'fieldset' : 'div';
return (
<div>
<Wrapper className="form-element">
<legend>{numberOfInputs} input(s)</legend>
<div>{children}</div>
</Wrapper>
</div>
)
}
const App = () => {
return (
<div>
<MyComp>
<MyInput placeholder="Some input #1" />
<div>
<span>Some non-input element</span>
</div>
</MyComp>
<MyComp>
<MyInput placeholder="Some input #1" />
<div>
<div>
<MyInput placeholder="Some nested input #2" />
</div>
<div>
<span>Some non-input element</span>
</div>
</div>
</MyComp>
</div>
)
}
ReactDOM.render(<App />, document.querySelector("#app"));