Skip to content

Instantly share code, notes, and snippets.

@dougalcorn
Created February 8, 2018 15:49
Show Gist options
  • Save dougalcorn/d91ff26034b5a1e9bb4c78aa677e97d9 to your computer and use it in GitHub Desktop.
Save dougalcorn/d91ff26034b5a1e9bb4c78aa677e97d9 to your computer and use it in GitHub Desktop.
Simple way to mount react components

This is a fairly simply way to bootstrap react components into server side rendered pages.

The server template has a div with data-component attribute who's value is the name of the component you want mounted. Each of the other data attributes are turned into properties for the component. It assumes the format is data-some-property-name and it's converted into a somePropertyName property.

For this to work, the component has to imported and assigned onto the global window namespace. The mountReactComponent function does an eval of the data-component name in order to create the React component.

If anything, this is the biggest weakness of this strategy. It requires poluting the global namespace with any of your top-level react components and also does a JS eval of strings from the markup. This could potentially be dangerous.

import MyComponent from './path/to/my_component';
window.MyComponent = MyComponent;
document.addEventListener('DOMContentLoaded', () => {
mountReactComponents();
});
import React from 'react';
import {render} from 'react-dom';
function snakeToCamel(s){
return s.replace(/(\-\w)/g, function(m){return m[1].toUpperCase();});
}
function snakeToCamelObject(o) {
var camelObject = {};
Object.keys(o).map((key) => {
let camelKey = snakeToCamel(key);
camelObject[camelKey] = o[key];
});
return camelObject;
}
export default function mountReactComponents() {
document.querySelectorAll(['[data-component]']).forEach((element) => {
let dataset = snakeToCamelObject(element.dataset),
componentName = dataset.component;
delete dataset.component;
let component = React.createElement(eval(componentName), dataset);
render(component, element);
});
}
<div data-component='MyComponent'
data-info="<%= get_flash(@conn, :info) %>"
data-error="<%= get_flash(@conn, :error) %>"
data-order-no="<%= @order.order_no %>"
data-other-param="<%= @param_value %>"
</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment