Skip to content

Instantly share code, notes, and snippets.

@jwo
Last active April 19, 2020 21:31
Show Gist options
  • Save jwo/7d9524d9075d129491d810cdf40f34b2 to your computer and use it in GitHub Desktop.
Save jwo/7d9524d9075d129491d810cdf40f34b2 to your computer and use it in GitHub Desktop.
register React component on page with turbolinks working. The Rails parts (helper and ERB) are optional, but since this IS turbolinks, you probably ARE using rails.
<h1>Oh Hai</h1>
<%= react_component 'oh-hai' %>
module ApplicationHelper
def react_component(container, props=nil)
content_tag(:div, nil, data: { "react-container": container, "react-props": props })
end
end
import {registerComponent} from 'registerComponent';
import OhHai from 'oh-hai';
document.addEventListener('turbolinks:load', () => registerComponent(OhHai, 'oh-hai'));
import React from 'react'
import ReactDOM from 'react-dom'
export function registerComponent (instance, container) {
const selector = `[data-react-container=${container}]`
let componentEntry = document.querySelector(selector)
if (componentEntry) {
const propsJSON = componentEntry.getAttribute("data-react-props")
const props = propsJSON && JSON.parse(propsJSON)
ReactDOM.render(React.createElement(instance, props),
componentEntry)
}
}
<div data-react-container="oh-hai"></div>
@slvtrs
Copy link

slvtrs commented Feb 15, 2018

This is a godsend!
I had to add a listener into registerComponent to trigger my components' unmount cycle, and then turbolinks and react finally got along without needing to rely on extra gems.

document.addEventListener('turbolinks:before-render', () => {
  ReactDOM.unmountComponentAtNode(componentEntry)
})

@jesster2k10
Copy link

I modified mine a little to automatically require all the components and format their names like:

./icons/Hamburger.tsx -> icons-hamburger like so:

document.addEventListener('turbolinks:load', () => {
  const context = require.context('components', true, /\.tsx$/)
  context.keys().forEach((key) => {
    const {default: Component} = require(`${key}`)
    const path = key
      .substr(2)
      .replace('/', '-')
      .replace('.tsx', '')
      .toLowerCase()
    registerComponent(Component, path)
  })
})

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment