2

This is regarding non-standard attributes. https://facebook.github.io/react/docs/tags-and-attributes.html

In react I have done this:

 React.createElement('div', {image:'blah', etc:'blah'});

I need image and etc to be set on the element with setAttribute, and I need react to use its smarts to maintain it as it changes.

A solution here https://stackoverflow.com/a/21654914/1828637 says to add it on componentDidMount but this is not a solution. The attribute will not be maintained as it changes by the react framework.

Is there anyway to tell react to set the attribute on my custom tags?

Community
  • 1
  • 1
Noitidart
  • 35,443
  • 37
  • 154
  • 323

3 Answers3

4

In react 16 custom attributes are now possible

// Your code:
<div mycustomattribute="something" />

// React 15 output:
<div /> 

// React 16 output:
<div mycustomattribute="something" />

react 16 custom attributes

Morris S
  • 2,337
  • 25
  • 30
2

This solution is to build on the linked answer by using the React lifecycle method componentWillReceiveProps to update the DOM element attributes with every change to props. For more information about all the lifecycle methods, see http://facebook.github.io/react/docs/component-specs.html.

(Since componentWillReceiveProps can be called more often than when the props actually change, you may wish to compare the props before actually setting them on the node.)

I've provide fiddle you can play with: https://jsfiddle.net/p4h267bo/ and the relevant part of the code is excerpted here:

var Hello = React.createClass({
  componentDidMount() {
    this.mirrorProps(this.props);
  },
  componentWillReceiveProps(nextProps) {
    this.mirrorProps(nextProps);
  },
  mirrorProps(props) {
    var node = ReactDOM.findDOMNode(this);
    node.setAttribute('name', props.name);
  },
  render: function() {
    return <div>Hello {this.props.name}</div>;
  }
});
Eric O'Connell
  • 858
  • 5
  • 14
  • Wow thank you so much for such a quick answer and it was superb! It worked fantastic I updated it to `shouldMirrorProps` in this fork of your fiddle - https://jsfiddle.net/Noitidart/wwLcbvfk/ - your fiddle helped me out immmmensely! This is a great answer I wish I could up vote you more so I fond your other answers and comments up voted them. – Noitidart Jan 21 '16 at 04:28
  • Will this work with `componentWillUpdate` as well? Or is `componentWillUpdate` only called if it is calculated that the DOM will change? Because some stuff I have in `this.state` that I want to mirror as attributes. – Noitidart Jan 21 '16 at 04:41
  • 1
    Now that I think about it, it might be better to do it in `componentDidUpdate`, because at that point you will know that any changes to the DOM have been flushed (in case you have some conditionals that would result in the DOM node going away — the current implementation only works because the node is stable). [Here's another fiddle!](https://jsfiddle.net/Lc9Lwpbf/1/) – Eric O'Connell Jan 21 '16 at 07:10
  • Thanks so much Eric! – Noitidart Jan 21 '16 at 07:11
  • 1
    I forgot to mention, if you are doing any kind of `shouldComponentUpdate` checks, you may want to include both `componentWillReceiveProps` and `componentDidUpdate` to be sure. `componentWillReceiveProps` still has access to `this.state`, and state updates will trigger `componentDidUpdate`. – Eric O'Connell Jan 21 '16 at 07:12
  • But what if there was no state or property changes that affected the dom? Will `componentDidUpdate` still get called? Like for instance, if only the custom attribute is to change in the dom, but if no dom changes prior to that happend Im worried `componentDidUpdate` won't call. – Noitidart Jan 21 '16 at 07:12
  • 1
    Unless you use `shouldComponentUpdate` to short-circuit the update after `setState`, React will still call `componentDidUpdate`. – Eric O'Connell Jan 21 '16 at 07:17
  • Ah thank you very much! I always thought that only triggered if the DOM was mutated in response to `setState`, so this assumption of mine is false? Is there such a event on the lifecycle? Sincere thanks! – Noitidart Jan 21 '16 at 12:15
2

Another alternative is to change the name of the attribute to something that react supports (such as the data-* attributes) :

render() {
    return (
      <div data-image='blah' data-etc='blah' />
    );
}

link to other supported attributes: https://facebook.github.io/react/docs/dom-elements.html

ohad serfaty
  • 644
  • 6
  • 11