6

As seen in another question, it is possible to loop through the child elements using React.Children.map. I am looking for a way to recursively traverse the child tree (props.children.props.children...) and substitute certain elements with another type of element. It would happen in a higher-order-component's render function.

Any help and ideas are greatly appreciated!

icetronics
  • 61
  • 1
  • 2

1 Answers1

7

You can build a recursive wrapper component that replaces any children it has and wraps its children in the same way. The replacement will continue recursively until child elements have no more children.

Here's an example of such a component. It substitutes <p> elements with <span> elements.

const RecursiveWrapper = props => {
    const wrappedChildren = React.Children.map(
        props.children,
        child => {
            const type = child.type === 'p' ? 'span' : child.type
            if (child.props && child.props.children) {
                return React.cloneElement(
                    {
                        ...child,
                        type // substitute original type
                    },
                    {
                        ...child.props,
                        // Wrap grandchildren too
                        children: (
                            <RecursiveWrapper>
                                {child.props.children}
                            </RecursiveWrapper>
                        )
                    }
                )
            }
            return child
        }
    )
    return (
        <React.Fragment>
            {wrappedChildren}
        </React.Fragment>
    )
}

You can use the same general idea to inject additional props as well.

Jemi Salo
  • 3,401
  • 3
  • 14
  • 25
  • Not sure this answers the question but this helped me so, upvote. Thanks. – Gunar Gessner Mar 25 '19 at 20:16
  • 1
    I would suggest to change the use of React.cloneElement to be more in accordance with the API, resulting in `React.cloneElement(child, {type}, ({child.props.children}))`. This can be done because the second argument are the patching props, and the third is the replacing children. The result is a more readable code. – Andre Knob Nov 28 '19 at 20:45