Skip to content

Instantly share code, notes, and snippets.

@jonknapp
Created April 6, 2019 13:04
Show Gist options
  • Save jonknapp/00baab4f73a3157ce172bb2c1c8d9967 to your computer and use it in GitHub Desktop.
Save jonknapp/00baab4f73a3157ce172bb2c1c8d9967 to your computer and use it in GitHub Desktop.
Dynamic React Component Finder in Rails with Webpacker
// app/javascript/packs/react.jsx
import React from "react";
import ReactDOM from "react-dom";
interface ComponentLookupTable {
[s: string]: Function;
}
function componentAlias(componentPath: string) {
if (componentPath.match(/index\.jsx?$/)) {
return componentPath.match(/\.\/(.+)\/index\.jsx?/)[1];
}
return componentPath.match(/\.\/(.+)\.jsx?/)[1];
}
function importAll(
requireFn: __WebpackModuleApi.RequireContext
): ComponentLookupTable {
return requireFn
.keys()
.filter(key => !key.match(/stories\.jsx?/))
.reduce((accumulator, key) => {
accumulator[
`[data-react-component="${componentAlias(key)}"]`
] = requireFn(key).default;
return accumulator;
}, {});
}
function setup(components: ComponentLookupTable) {
Object.keys(components).forEach(selector => {
const Component = components[selector];
const elements: NodeListOf<HTMLElement> = document.querySelectorAll(
selector
);
elements.forEach(element => {
if (element.children.length === 0) {
const initialProps = JSON.parse(element.dataset.reactProps || "{}");
ReactDOM.render(<Component {...initialProps} />, element);
}
});
});
}
function teardown(components: ComponentLookupTable) {
Object.keys(components).forEach(teardownElement);
}
function teardownElement(selector) {
const elements = document.querySelectorAll(selector);
elements.forEach(ReactDOM.unmountComponentAtNode);
}
const components = importAll(
require.context("../components/.", true, /\.jsx?$/)
);
document.addEventListener(
"turbolinks:before-render",
teardown.bind(null, components)
);
document.addEventListener("turbolinks:load", setup.bind(null, components));
setup(components);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment