# this is heavily influenced by react-rails: # https://github.com/reactjs/react-rails/blob/master/lib/react/server_rendering/exec_js_renderer.rb class ExecJsRenderer JS_TEMPLATE = <<~JS var execJsGlobal = {}; var self = self || this; var window = window || this; JS def initialize(js_code) @context = ExecJS.compile(JS_TEMPLATE + js_code) end def render(component_name, props) js_code = <<~JS (function() { var component = execJsGlobal["#{component_name}"]; var sheet = new execJsGlobal.ServerStyleSheet(); var element = execJsGlobal.React.createElement(component, #{props.to_json}); var html = execJsGlobal.ReactDOMServer.renderToString(sheet.collectStyles(element)); var styles = sheet.getStyleTags(); return html + styles; })() JS @context.eval(js_code).html_safe end private def compose_js(js) <<~JS (function() { var result = #{js}; return result; })() JS end end