Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React: Can I add attributes to children's resultant HTML?

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.

like image 387
Pablo Lozano Avatar asked Oct 18 '25 02:10

Pablo Lozano


1 Answers

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>)
  }
}
like image 119
Yury Tarabanko Avatar answered Oct 19 '25 17:10

Yury Tarabanko