96

There are different reasons behind it, but I wonder how to simply add custom attributes to an element in JSX?

KARTHIKEYAN.A
  • 18,210
  • 6
  • 124
  • 133
Andrey Borisko
  • 4,511
  • 2
  • 22
  • 31
  • May be one comment help someone, i found out React 16.7 ***doesnt rerenders*** and update the component's html attributes if you changed only them in a store (f.e. redux) and tied to component. This means the component has f.e.```aria-modal=true```, you push the changes (to false) to the store of **aria/data** attributes, but nothing else is changed (such as component's content or class or variables in there) as the result ReactJs will not update **aria/data** attrs in that components. I've been messing around about whole day to realise that. – Alexey Nikonov Feb 13 '19 at 09:48

11 Answers11

93

EDIT: Updated to reflect React 16

Custom attributes are supported natively in React 16. This means that adding a custom attribute to an element is now as simple as adding it to a render function, like so:

render() {
  return (
    <div custom-attribute="some-value" />
  );
}

For more:
https://reactjs.org/blog/2017/09/26/react-v16.0.html#support-for-custom-dom-attributes
https://facebook.github.io/react/blog/2017/09/08/dom-attributes-in-react-16.html


Previous answer (React 15 and earlier)

Custom attributes are currently not supported. See this open issue for more info: https://github.com/facebook/react/issues/140

As a workaround, you can do something like this in componentDidMount:

componentDidMount: function() {
  var element = ReactDOM.findDOMNode(this.refs.test);
  element.setAttribute('custom-attribute', 'some value');
}

See https://jsfiddle.net/peterjmag/kysymow0/ for a working example. (Inspired by syranide's suggestion in this comment.)

peterjmag
  • 6,041
  • 1
  • 30
  • 27
  • yeah, only this way I guess. [this](https://github.com/facebook/react/issues/140#issuecomment-66755379) approach looks interesting though – Andrey Borisko Jul 07 '15 at 16:53
  • 1
    i'm a total react n00b so sorry if this is a stupid question, but why not just add all the custom attributes in the ref callback? eg: ref={(thisSvgElement) => { thisSvgElement.setAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink'); }} – k7n4n5t3w4rt Dec 08 '16 at 23:19
  • @k7n4n5t3w4rt Yep, that should work too. Ref callbacks just didn't exist back when I wrote this answer. – peterjmag Dec 19 '16 at 23:01
  • 1
    This isn't entirely true. You can add a custom attribute by prepending it with `data-` or `aria-`. See [Luca's answer](https://stackoverflow.com/a/44569018/6131801) and/or the [React Docs](https://facebook.github.io/react/docs/dom-elements.html) – Scott Aug 24 '17 at 22:40
  • Why can you not do this on components so that the attr will be rendered on the first element in the render? – Nikos Aug 07 '19 at 16:22
59

You can add an attribute using ES6 spread operator, e.g.

let myAttr = {'data-attr': 'value'}

and in render method:

<MyComponent {...myAttr} />
Spadar Shut
  • 15,111
  • 5
  • 47
  • 54
  • Do you think this `let myAttr = {'custom-attr': 'value'}` would work? – Andrey Borisko Nov 08 '16 at 16:25
  • 2
    It does work if you have a ES6 transpiler in your project – Spadar Shut Nov 10 '16 at 11:41
  • 2
    well, here is a [codepen example](http://codepen.io/andrx/pen/GNopRB?editors=0010). I don't see custom attribute there – Andrey Borisko Nov 10 '16 at 14:05
  • @AndreyBorisko - The attributes will be effective as long as they are valid HTML5 attributes. I forked your pen and made changes: http://codepen.io/deveedutta/pen/ObqEQL The button is clearly disabled. – DDM Dec 21 '16 at 06:48
  • @DDM `disabled` is not a custom attribute. It's a standard HTML attribute. Have I missed something in your example? – Andrey Borisko Dec 21 '16 at 15:48
  • 6
    @AndreyBorisko - I intended to mention but missed, that invalid html attributes and custom attributes won't work as of now unless pre-fixed by `data-`. – DDM Dec 22 '16 at 05:52
  • 1
    I think this answer is misleading because the question is specific to custom attributes and the solution proposed by @peterjmag is the correct one. – Kevin Farrugia Sep 23 '17 at 07:27
  • @KevinFarrugia data attrubutes are still custom attributes, and adding attributes to a DOM via `element.setAttribute('custom-attribute', 'some value');` isn't JSX at all. – Spadar Shut Oct 04 '17 at 09:29
29

Consider you want to pass a custom attribute named myAttr with value myValue, this will work:

<MyComponent data-myAttr={myValue} />
Luca Fagioli
  • 12,722
  • 5
  • 59
  • 57
  • 2
    @GusDeCool First of all it is stated that was tested with react `15.3.1`, so your downvote does not make any sense since you are complaining that it does not work with `15.5.4`. Second, I have just test it with `^15.6.1` and it works just fine. Double check your code. – Luca Fagioli Jun 21 '17 at 07:45
  • 2
    ah i see, it was on `react-dom` not `react`. sorry, my bad :). – GusDeCooL Jun 21 '17 at 07:48
  • 4
    This is the correct answer. You can add custom attributes by prepending them with either `data-` or `aria-`. See also: https://facebook.github.io/react/docs/dom-elements.html – Scott Aug 24 '17 at 22:42
  • **react 16 and on** – Morris S Oct 25 '17 at 03:19
  • 1
    This feels like the most HTML5 compliant answer – jcollum May 31 '18 at 00:42
  • @MorrisS This is not correct, because it actually works since react 15.6.x. – Luca Fagioli Jun 11 '18 at 11:42
13

if you are using es6 this should work:

<input {...{ "customattribute": "somevalue" }} />
Squibly
  • 335
  • 2
  • 7
12

You can use the "is" attribute to disable the React attribute whitelist for an element.

See my anwser here: Stackoverflow

Community
  • 1
  • 1
Christian Steinmann
  • 1,156
  • 1
  • 11
  • 13
5

I ran into this problem a lot when attempting to use SVG with react.

I ended up using quite a dirty fix, but it's useful to know this option existed. Below I allow the use of the vector-effect attribute on SVG elements.

import SVGDOMPropertyConfig from 'react/lib/SVGDOMPropertyConfig.js';
import DOMProperty from 'react/lib/DOMProperty.js';

SVGDOMPropertyConfig.Properties.vectorEffect = DOMProperty.injection.MUST_USE_ATTRIBUTE;
SVGDOMPropertyConfig.DOMAttributeNames.vectorEffect = 'vector-effect';

As long as this is included/imported before you start using react, it should work.

rbhalla
  • 869
  • 8
  • 32
3

See attribute value in console on click event

//...
   alertMessage (cEvent){
           console.log(cEvent.target.getAttribute('customEvent')); /*display attribute value */
        }
//...

simple add customAttribute as your wish in render method

render(){
    return <div>
//..
    <button customAttribute="My Custom Event Message" onClick={this.alertMessage.bind(this) } >Click Me</button>
            </div>
        }
//...
GMKHussain
  • 3,342
  • 1
  • 21
  • 19
2

Depending on what version of React you are using, you may need to use something like this. I know Facebook is thinking about deprecating string refs in the somewhat near future.

var Hello = React.createClass({
    componentDidMount: function() {
        ReactDOM.findDOMNode(this.test).setAttribute('custom-attribute', 'some value');
    },
    render: function() {
        return <div>
            <span ref={(ref) => this.test = ref}>Element with a custom attribute</span>
        </div>;
    }
});

React.render(<Hello />, document.getElementById('container'));

Facebook's ref documentation

2

uniqueId is custom attribute.

<a {...{ "uniqueId": `${item.File.UniqueId}` }}  href={item.File.ServerRelativeUrl} target='_blank'>{item.File.Name}</a>
Vaibhav Bhatia
  • 528
  • 1
  • 4
  • 12
1

Depending on what exactly is preventing you from doing this, there's another option that requires no changes to your current implementation. You should be able to augment React in your project with a .ts or .d.ts file (not sure which) at project root. It would look something like this:

declare module 'react' {
    interface HTMLAttributes<T> extends React.DOMAttributes<T> {
        'custom-attribute'?: string; // or 'some-value' | 'another-value'
    }
}

Another possibility is the following:

declare namespace JSX {
    interface IntrinsicElements {
        [elemName: string]: any;
    }
}

See JSX | Type Checking

You might even have to wrap that in a declare global {. I haven't landed on a final solution yet.

See also: How do I add attributes to existing HTML elements in TypeScript/JSX?

jedmao
  • 10,224
  • 11
  • 59
  • 65
1

For any custom attributes I use react-any-attr package https://www.npmjs.com/package/react-any-attr

Itay Merchav
  • 954
  • 8
  • 8