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