Until today, when I wrote some documentation in a small side project, and I took the opportunity to try and solve that problem. It was actually quite simple when working with webpack, since it allows you to bundle some HTML content and require it as a string from your JavaScript components. Once you have your HTML loaded in a string, there is a very simple way to turn it into React DOM elements: dangerouslySetInnerHTML. That function should never be used when you cannot trust the content you include, but that is obviously not the case here.

To bundle some HTML content with webpack, install the html-loader module: npm install --save-dev html-loader. To use that loader automatically for HTML files, here's the configuration you can add to your webpack.config.js:

{
  modules: {
    loaders: [
      { test: /\.html$/, loader: 'html' }
    ]
  }
}

Then simply require your HTML file from any JS file, with var htmlContent = require('path/to/html/file.html'); or import htmlContent from 'path/to/html/file.html'); if you are using ES6. Let's say we are using babel, this is what our file could look like:

import React from 'react';
import htmlContent from 'path/to/file.html';

export default function MyComponent() {
    return (
        <div dangerouslySetInnerHTML={ {__html: htmlContent} } />
    );
}

So, the good thing about this is that you can write your long HTML content in separate files, without some of the hassles of JSX (like having to use className instead of class). It will keep your components small and with a clean separation of concerns. The downside is that you cannot use anything other than HTML in that separate file, so no React components for example.