1

I'm trying to add a custom HTML attribute on a React component:

const Parent = () => (
    <div className="parent">
      <Child data-custom="foo" />
    </div>
);

Where Child is another React component, but the attribute gets stripped on the output HTML. I'm aware that I could simply add the attribute on the Child root element, like so:

 const Child = () => <div className="child" data-custom="foo" />

Or read the attribute in the Child component via props, but that's not what i'm looking since that would couple the attribute with the component, and I'm looking for a more contextual approach (the attribute would be used for test automation purposes).

Is there a clean way to do that in React?

I'm also considering writing a Babel plugin to add the attribute or prevent the stripping, but that would be another question.

Thanks!

Vikas Yadav
  • 3,094
  • 2
  • 20
  • 21
Carlos
  • 119
  • 1
  • 8

3 Answers3

1

React element doesn't necessarily correspond to DOM element that could have HTML attributes. React component can be rendered to multiple DOM elements or no elements at all.

If Child should be able to provide additional props or attributes to child DOM element, it should pass them explicitly:

const Child = props => <div className="child" {...props} />

This way data-custom="foo" will be passed to <div>.

Estus Flask
  • 206,104
  • 70
  • 425
  • 565
  • I'm very new to React, wasn't aware that React components could be rendered to no DOM elements. This solution works! Thanks! I'll stick to it, although i was trying to avoid explicitly managing props inside each component. Maybe a hook or a babel plugin? – Carlos Apr 11 '19 at 08:07
  • I'm not aware of any helper, and this would be tricky because it needs to hook into React renderer to do this. And still, it's unclear how it should work if a component returns not DOM element but something else. E.g. `Child` returns `Fragment` with multiple children. Should it discard data attribute or give it to all children? FWIW, there's a convention over `data-testid` attribute that is used by react-testing-library, see https://testing-library.com/docs/dom-testing-library/api-queries#bytestid . The attribute is supposed to be set manually on significant elements. – Estus Flask Apr 11 '19 at 09:53
0

For this, you can try this in your react script.

const MyCompo = () => {
 return (
  <div>
   <p>HTML Code</p>
  </div>
 );
}
export default About;

Otherwise you can create class and then define your components and then export them.

import React from 'react';

import '../assets/css/style.css';
import '../assets/css/pure-min.css';
import '../assets/css/custom.css';
import 'font-awesome/css/font-awesome.min.css';
import $ from 'jquery';

class FirstScreen extends React.Component {
 constructor(props) {
     super(props);
     this.handleLoad = this.handleLoad.bind(this);
 }
 componentDidMount() {
  window.addEventListener('load', this.handleLoad);
 }
 handleLoad() {
  
  }

 render() {
  return <div>HTML Code</div>;
 }
}

export default FirstScreen;
0

You could use the below syntax

const Parent = () => (
    <div className="parent">
      <Child data-custom="foo"/>
    </div>
);
const Child = ({...props}) => (<div className="child" {...props} />)