For a component I'm building I'm recursively looping over its child components using React.Children.map
to make modifications to their props. The basic structure is like this:
// main component
const Main = ({ children }) => recursivelyModifyChildProps(children);
// recursive function
function recursivelyModifyChildProps(children) {
return React.Children.map(children, (child) => {
// if no valid react element, just return it
if (!React.isValidElement(child)) {
return child;
}
// check if child isn't a `<Main/>` component
// not sure about this check
if (typeof child.type !== 'string' && child.type.name === 'Main') {
return child;
}
const { children, ...restProps } = child.props;
// do stuff to create new props
const newProps = { foo: 'bar' };
// return new element with modified props
return React.createElement(
child.type,
{
...restProps,
...newProps,
children: recursivelyModifyChildProps(children)
}
);
});
}
Children of Main
will have their props modified via recursivelyModifyChildProps
and their children will have their props modified, etc. I want to do this unless the child component is an instance of the Main
component, in that case it should be returned unmodified. Currently I'm doing this via child.type.name
, and this does work. However, this implementation is very bug prone I believe, since everyone could call their component "Main". What is the best (or at least a better) way to figure out that a component is an instance a particular (functional) component, or an instance of itself?
You can validate it by comparing the child.type
to Main
instance which is unique.
if (child.type === Main) {
return undefined;
}
A full example of modifying all Main
children with skipping the Main
instance.
import React from 'react';
import ReactDOM from 'react-dom';
const Main = ({ children }) => recursivelyModifyChildProps(children);
function recursivelyModifyChildProps(children) {
return React.Children.map(children, child => {
if (!React.isValidElement(child)) {
return child;
}
if (child.type === Main) {
return undefined;
}
const { children, ...restProps } = child.props;
const newProps = { foo: 'bar' };
return React.createElement(child.type, {
...restProps,
...newProps,
children: recursivelyModifyChildProps(children)
});
});
}
const App = () => {
return (
<Main>
// v Main is skipped
<Main />
<div>Hello</div>
</Main>
);
};
ReactDOM.render(<App />, document.getElementById('root'));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With