I have a component that wraps other components:
class MyComp extends React.Component {
render() {
return <div> {this.props.children} </div>
}
}
Let's say I add another random component as a child:
<MyComp><FancyP>Hello</FancyP></MyComp>
The resultant HTML would be like this:
<div>
<p class="fancy'>Hello</p>
</div>
I know that using React.Children
I could add new props to the child component, but what I really want to do is add custom attributes to the resultant HTML of any random child, having something like this:
<MyComp childAttr={{'data-x':'value'}}><FancyP>Hello</FancyP></MyComp>
that would generate the following:
<div>
<p class="fancy' data-x='value'>Hello</p>
</div>
Is there a way to achieve this? Adding a props to the children does not work because children's classes are not aware of the new props and they ignore them.
Not sure why you need this and I do recommend you to rethink your architecture before it is too late.
But you can do a little bit of a hackery using ReactDOM.findDOMNode
.
First you need to set refs for every child component. By cloning element and assigning a ref.
Then attach hooks on componentDidMount
and componentDidUpdate
events, find dom element using findDOMNode
and manually populate dataset. DEMO.
import React, { Component, Children, cloneElement } from 'react'
import { render, findDOMNode } from 'react-dom'
class MyComp extends Component {
componentDidMount() {
this.setChildAttrs()
}
componentDidUpdate() {
this.setChildAttr()
}
setChildAttrs() {
const { childAttrs } = this.props
const setAttrs = el => Object.keys(childAttrs)
.forEach(attr => el.dataset[attr] = childAttrs[attr])
// for each child ref find DOM node and set attrs
Object.keys(this.refs).forEach(ref => setAttrs(findDOMNode(this.refs[ref])))
}
render() {
const { children } = this.props
return (<div> {
Children.map(children, (child, idx) => {
const ref = `child${idx}`
return cloneElement(child, { ref });
})} </div>)
}
}