22

The site I am developing makes use of Microdata (using schema.org). As we are shifting development over to use React to render our views I have hit a blocker where React will only render attributes in the HTML spec however Microdata specifies custom attributes such as itemscope.

As I'm relatively new to React and haven't had chance to fully understand the core just yet, my question is what would be the best way to extend the functionality of react.js to allow for defined custom attributes, e.g., Microdata?

Is there a way of extending the attributes/props parser or is it a job for a mixin which checks all passed props and modifies the DOM element directly?

(Hopefully we'll be able to put together a drop in extension for everyone to provide support for this when a solution is clear.)

Dmitry Shvedov
  • 3,169
  • 4
  • 39
  • 51
Chris Pearce
  • 1,706
  • 4
  • 15
  • 18
  • Note that these (`itemscope`, …) are attributes defined by Microdata, not schema.org. (schema.org is "just" a vocabulary, i.e. it defines values that can be used for those attributes). – unor Feb 09 '14 at 02:13
  • To save others some time - https://github.com/facebook/react/issues/140 – Kamil Tomšík Jun 21 '15 at 08:19

5 Answers5

54

You can also use "is" attribute. It will disable the attribute white-list of React and allow every attribute. But you have to write class instead of className and for instead of htmlFor if you use is.

<div is my-custom-attribute="here" class="instead-of-className"></div>

Update React 16 custom attributes are now possible

In react 16 custom attributes are now possible

React 16 custom attributes

Christian Steinmann
  • 1,156
  • 1
  • 11
  • 13
  • 1
    This should be the correct answer, as the accepted answer does not work for elements that are not React components, like _``_, or _WebComponents_. – AP. Mar 01 '17 at 22:00
  • Can be found in a function named isCustomComponent https://github.com/facebook/react/blob/27c844905fcbb64ca0ba7c0a6b0fa0e121f9c429/src/renderers/dom/stack/client/ReactDOMComponent.js#L371 – Christian Steinmann Apr 10 '17 at 05:16
  • 1
    This seems to be an undocumented "feature" of React. As such, I would be worried that it is unstable and may end up pinning you to a specific React version if you used it. – Nick G. Aug 22 '17 at 18:37
14

It looks like these non-standard properties have been added to React

itemProp: MUST_USE_ATTRIBUTE, // Microdata: http://schema.org/docs/gs.html
itemScope: MUST_USE_ATTRIBUTE | HAS_BOOLEAN_VALUE, // Microdata: http://schema.org/docs/gs.html
itemType: MUST_USE_ATTRIBUTE, // Microdata: http://schema.org/docs/gs.html

Note that properties have capital letter in the middle:

<div itemProp="whatever..." itemScope itemType="http://schema.org/Offer">

will generate proper lowercase attributes as result.

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
Reggie Pharkle
  • 140
  • 1
  • 4
  • how do we use these in react? Can I just put the tag `
    {this.props.data.question} - on dialectic.sg
    ` into the react render()?
    – GK79 Aug 23 '15 at 16:00
  • 1
    Hi @reggie-pharkle - I'd really like to know where I can learn more about how to use those non-standard properties. Thanks! – GK79 Aug 25 '15 at 15:33
  • 3
    Just to be clear itemScope and ItemType are cammelCase – doron aviguy Sep 06 '15 at 09:41
10

You should be able to do it with componentDidMount:

...
componentDidMount: function() {
  if (this.props.itemtype) {
    this.getDOMNode().setAttribute('itemscope', true)
    this.getDOMNode().setAttribute('itemtype', this.props.itemtype)
  }

  if (this.props.itemprop) {
    this.getDOMNode().setAttribute('itemprop', this.props.itemprop)
  }
}
...

The whole check for Microdata attributes can be wrapped into a mixin for convenient. The problem with this approach is that it won't work for built-in React component (components created by React.DOM). Update: Looking closer at React.DOM, I come up with this http://plnkr.co/edit/UjXSveVHdj8T3xnyhmKb?p=preview. Basically we wrap the built-in components in a custom component with our mixin. Since your components are built upon React 's built-in DOM components, this would work without you having to include the mixin in the components.

The real solution would be injecting a custom config instead of React's DefaultDOMPropertyConfig, however I can't find a way to do so in a drop-in manner (DOMProperty is hidden by the module system).

tungd
  • 14,467
  • 5
  • 41
  • 45
  • 10
    We (react team) are looking at options to make this injectible at run time so people can use custom DOM properties. For the mean time, this is the best option, unless you want to use a custom build. – Paul O'Shannessy Feb 09 '14 at 21:19
  • Paul I dont suppose you could update us on any progress you guys have made in this regard? Thanks – Thomas Clowes Jul 19 '14 at 20:36
  • It seems they are actually attempting to get this in [right now](https://github.com/facebook/react/pull/7311). – Stijn de Witt Jul 06 '17 at 11:13
6

For those who's still looking for answers: https://facebook.github.io/react/docs/tags-and-attributes.html

Example:

<div itemScope itemType="http://schema.org/Article"></div>
Monyetz
  • 69
  • 1
  • 2
0

So far, the best method I've found is based off of some Amp interop code linked from a comment on react's bug tracker thread on the subject. I modified it slightly to work with a newer version of React (15.5.4) and TypeScript.

For regular ES6, you can just remove the type annotation for attributeName. Using require was needed in TS since DOMProperty isn't exposed in react's index.d.ts, but again import could be used in regular ES6.

// tslint:disable-next-line:no-var-requires
const DOMProperty = require("react-dom/lib/DOMProperty");
if (typeof DOMProperty.properties.zz === "undefined") {
    DOMProperty.injection.injectDOMPropertyConfig({
        Properties: { zz: DOMProperty.MUST_USE_ATTRIBUTE },
        isCustomAttribute: (attributeName: string) => attributeName.startsWith("zz-")
    });
}

Now you can use any attribute starting with zz-

<div zz-context="foo" />

Normally it'd be a bad idea to use internal parts of react like this, but I think it is better than any of the other methods. It works the same way as existing open-ended attributes like data- and the JSX is even type safe in TS. I believe the next major version of react is going to do away with the whitelist anyway, so hopefully changes won't be needed before we can remove this shim entirely.

ShawnFumo
  • 2,108
  • 1
  • 25
  • 14