I had implemented an Angular 4 dynamic DOM prototype using the Angular Dynamic Component Loader and wanted to do the same thing with React JS. After doing some research I found that it was not very obvious how to accomplish this.

By the time I was done there ended up being two functional components worth sharing:

In the demo application, all available components register themselves via the ComponentService, which is just a singleton that maintains a simple hash map. For example:

JavaScript

1

ComponentService.addComponent('switch',SwitchComponent);

As highlighted on lines 17-18, the desired React Component is first fetched from the ComponentService and then passed to JSX via <this.component … />.

The JSX preprocessor converted this embedded HTML into Javascript with the ‘React Element’ type set to the passed Component along with the additional attributes. I.e. if the UI type was ‘switch’, the hard-coded HTML would have been <SwitchComponent … /> which is a perfectly acceptable JSX template.

Voilà, we have created a dynamic DOM element!

Note that Vue.js applications using JSX can use the same technique except they pass a Vue Component instead.

JSON Driven Dynamic DOM Generation

In order to demonstrate dynamic DOM generation I have defined a simple UI JSON structure. The demo uses Bootstrap panels for the group and table elements and only implements a few components.

The UI JSON is loaded from the server when the application is started and drives the DOM generation. A DynamicComponent is passed a context (i.e. its associated JSON object) along with a path (see below). Each UI element has the following attributes:

name: A unique name within the current control context. It is used to form the namespace-like path that allows this component to be globally identified.

ui: The type of UI element (e.g. “output”, “switch”, etc.). This is mapped by the ComponentService to its corresponding React Component. If the UI type is not registered, the DefaultComponent is used.

label: Label used on the UI.

controls: (optional) For container components (“group”, “table”), this is an array of contained controls.

value: (optional) For value-based components.

range: (optional) Specifies the min/max/step for the range component.

This structure can easily be extended to meet custom needs.

There are a number of implementation details that I’m not covering in this post. I think the demo application is simple enough that just examining and playing with the code should answer any questions. If not, please ask.

The resulting output, including console logging from the switch and range components, looks like this.

This is, of course, a very minimal implementation that was designed to just demonstrate dynamic DOM generation. In particular, there is no UI event handling, data binding, or other interactive functionality that would be required to make a useful application.