Using x-tags from Mozilla, we can write custom tags within the DOM. This is a great opportunity to be able to write reusable components without being tied to a particular library. I wrote x-react to have them being rendered in React.
Example
We're first going to write a regular React component.
var Hello = React.createClass({ render: function() { return <div>{'Hello ' + this.props.name}</div>; } }); |
Then, we use xreact.register to bind a React component to a custom tag name.
xreact.register('x-hello', Hello); |
At this point, any DOM element will be rendered using React.
<x-hello name="World"></x-hello> |
The rendered DOM tree lives in the shadow DOM. This lets us manipulate both the component as well as the rendered <div> using Web Inspector.

Anytime you modify the component, whether it is in the inspector or in Javascript with the regular DOM API, React is going to be invoked to update the rendered version.
Behind the scenes
When you call xreact.register, we call xtag.register saying that whenever an DOM element is created, we render a special component called XReact in the shadow root of <x-hello>.
xtag.register('x-hello', { lifecycle: { created: function() { React.renderComponent( XReact({element: this}), this.createShadowRoot() ); } } }); |
XReact is a really simple component that takes a DOM node, in this case <x-hello name="World" /> and converts it to the React equivalent: Hello({name: 'World'}).
var XReact = React.createClass({ render: function() { return convertDOMToReact(this.props.element); } |
MutationObserver gives us a callback whenever the DOM element is changed. We just have to call this.forceUpdate() to make sure the React rendered version stays in sync.
componentDidMount: function() { new MutationObserver(this.forceUpdate.bind(this)).observe( this.props.element, {/* all the possible mutations */} ); } ); |
That's it 🙂
Conclusion
It was really easy to make this small bridge in order to be able to create custom tags and have them rendered using React. Unfortunately, this experiment is only working on Chrome as it is relying on MutationObserver and Shadow DOM.