I\'m trying to find the proper way to define some components which could be used in a generic way:
According to the documentation of cloneElement()
React.cloneElement(
element,
[props],
[...children]
)
Clone and return a new React element using element as the starting point. The resulting element will have the original element’s props with the new props merged in shallowly. New children will replace existing children. key and ref from the original element will be preserved.
React.cloneElement()
is almost equivalent to:<element.type {...element.props} {...props}>{children}</element.type>
However, it also preserves refs. This means that if you get a child with a ref on it, you won’t accidentally steal it from your ancestor. You will get the same ref attached to your new element.
So cloneElement is what you would use to provide custom props to the children. However there can be multiple children in the component and you would need to loop over it. What other answers suggest is for you to map over them using React.Children.map
. However React.Children.map
unlike React.cloneElement
changes the keys of the Element appending and extra .$
as the prefix. Check this question for more details: React.cloneElement inside React.Children.map is causing element keys to change
If you wish to avoid it, you should instead go for the forEach
function like
render() {
const newElements = [];
React.Children.forEach(this.props.children,
child => newElements.push(
React.cloneElement(
child,
{...this.props, ...customProps}
)
)
)
return (
<div>{newElements}</div>
)
}
The best way, which allows you to make property transfer is children
like a function pattern
https://medium.com/merrickchristensen/function-as-child-components-5f3920a9ace9
Code snippet: https://stackblitz.com/edit/react-fcmubc
Example:
const Parent = ({ children }) => {
const somePropsHere = {
style: {
color: "red"
}
// any other props here...
}
return children(somePropsHere)
}
const ChildComponent = props => <h1 {...props}>Hello world!</h1>
const App = () => {
return (
<Parent>
{props => (
<ChildComponent {...props}>
Bla-bla-bla
</ChildComponent>
)}
</Parent>
)
}