Skip to content

Instantly share code, notes, and snippets.

@maxim maxim/react.rb
Created Jun 28, 2019

Embed
What would you like to do?
Extending react-rails with styled components support
# config/initializers/react.rb
Rails.configuration.react.server_renderer =
Class.new(React::ServerRendering::BundleRenderer) do
private
def render_from_parts(before, main, after)
js_code = compose_js(before, main, after)
@context.eval(js_code)
end
def compose_js(before, main, after)
<<-JS
(function () {
#{before}
var data = #{main};
var result = data['html'];
#{after}
return data;
})()
JS
end
end
Rails.configuration.react.view_helper_implementation =
Class.new(React::Rails::ComponentMount) do
def setup(*)
super.tap { init_component_styles }
end
private
def prerender_component(*)
data = super
case data
when Hash
register_component_style(data['styles'])
data['html'].html_safe
else
data.html_safe
end
end
def init_component_styles
@controller.instance_variable_set(:@styled_component_styles, '')
end
def register_component_style(style)
@controller.instance_variable_get(:@styled_component_styles) << style.to_s
end
end
import React from 'react';
import ReactRailsUJS from 'react_ujs';
import ReactDOMServer from 'react-dom/server';
import { ServerStyleSheet } from 'styled-components';
const componentRequireContext = require.context('components', true);
ReactRailsUJS.useContext(componentRequireContext);
ReactRailsUJS.serverRender = function(renderFunction, componentName, props) {
const ComponentConstructor = this.getConstructor(componentName);
const stylesheet = new ServerStyleSheet();
const wrappedElement = stylesheet.collectStyles(
<ComponentConstructor {...props} />,
);
const html = ReactDOMServer[renderFunction](wrappedElement);
return {
html,
styles: stylesheet.getStyleTags(),
};
};
<#% put this line where you want styles to go %>
<%= raw @styled_component_styles.to_s %>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.