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.

If you liked this article, you might be interested in my Twitter feed as well.
 
 

Related Posts

  • February 23, 2012 Dassault Systemes Javascript Evangelism Talk (4)
    I recently had the chance to do a 2-hour Javascript evangelism talk at Dassault Systèmes. Unfortunately the presentation has not been recorded. I reused my the presentation I did at EPITA at the beginning and added a second part with a lot of demos. I've written down notes about the […]
  • October 12, 2011 Intercept and alter <script> include (2)
    For a project, I want to transparently be able to intercept all the included javascript files, edit the AST and eval it. This way I can manipulate all the code of an application just by inserting a custom script. Hook the <script> tag insertion. Download the Javascript file […]
  • August 27, 2011 Start a technical blog, it’s worth it! (6)
    Lately, I've been advocating to all my student friends to start a blog. Here's an article with the most common questions answered :) What are the benefits? Being known as an expert. The majority of my blog posts are about advanced Javascript topics. As a result, I'm being tagged as […]
  • November 27, 2013 JSX: E4X The Good Parts (9)
    E4X (ECMAScript for XML) is a Javascript syntax extension and a runtime to manipulate XML. It was promoted by Mozilla but failed to become mainstream and is now deprecated. JSX was inspired by E4X. In this article, I'm going to go over all the features of E4X and explain the design […]
  • November 5, 2011 Simulated Annealing Project (2)
    For a school project, I have to implement Simulated Annealing meta heuristic. Thanks to many open source web tools, I've been able to quickly do the project and have a pretty display. CoffeeScript, Raphael, Highcharts, Three.js, Twitter Bootstrap, jQuery and Web […]