Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 26 additions & 10 deletions lib/react/server_rendering/exec_js_renderer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,10 @@ def initialize(options={})
end

def render(component_name, props, prerender_options)
render_function = prerender_options.fetch(:render_function, "renderToString")
js_code = <<-JS
(function () {
#{before_render(component_name, props, prerender_options)}
var result = ReactDOMServer.#{render_function}(React.createElement(#{component_name}, #{props}));
#{after_render(component_name, props, prerender_options)}
return result;
})()
JS
@context.eval(js_code).html_safe
js_executed_before = before_render(component_name, props, prerender_options)
js_executed_after = after_render(component_name, props, prerender_options)
js_main_section = main_render(component_name, props, prerender_options)
render_from_parts(js_executed_before, js_main_section, js_executed_after)
rescue ExecJS::ProgramError => err
raise React::ServerRendering::PrerenderError.new(component_name, props, err)
end
Expand All @@ -36,6 +30,28 @@ def after_render(component_name, props, prerender_options); ""; end
var window = window || this;
JS

private

def render_from_parts(before, main, after)
js_code = compose_js(before, main, after)
@context.eval(js_code).html_safe
end

def main_render(component_name, props, prerender_options)
render_function = prerender_options.fetch(:render_function, "renderToString")
"ReactDOMServer.#{render_function}(React.createElement(#{component_name}, #{props}))"
end

def compose_js(before, main, after)
<<-JS
(function () {
#{before}
var result = #{main};
#{after}
return result;
})()
JS
end
end
end
end
45 changes: 33 additions & 12 deletions lib/react/server_rendering/sprockets_renderer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,14 @@ def initialize(options={})
super(options.merge(code: js_code))
end

# Prerender options are expected to be a Hash however might also be a symbol.
# pass prerender: :static to use renderToStaticMarkup
# pass prerender: true to enable default prerender
# pass prerender: {} to proxy some custom options
def render(component_name, props, prerender_options)
# pass prerender: :static to use renderToStaticMarkup
react_render_method = if prerender_options == :static
"renderToStaticMarkup"
else
"renderToString"
end

if !props.is_a?(String)
props = props.to_json
end

super(component_name, props, {render_function: react_render_method})
t_options = prepare_options(prerender_options)
t_props = prepare_props(props)
super(component_name, t_props, t_options)
end

def after_render(component_name, props, prerender_options)
Expand Down Expand Up @@ -76,6 +71,32 @@ def asset_container
def assets_precompiled?
!::Rails.application.config.assets.compile
end

private

def prepare_options(options)
r_func = render_function(options)
opts = case options
when Hash then options
when TrueClass then {}
else
{}
end
# This seems redundant to pass
opts.merge(render_function: r_func)
end

def render_function(opts)
if opts == :static
'renderToStaticMarkup'.freeze
else
'renderToString'.freeze
end
end

def prepare_props(props)
props.is_a?(String) ? props : props.to_json
end
end
end
end
19 changes: 19 additions & 0 deletions test/react/server_rendering/sprockets_renderer_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,29 @@

when_sprockets_available do
class SprocketsRendererTest < ActiveSupport::TestCase
CALLBACKS = [:before_render, :after_render]

setup do
@renderer = React::ServerRendering::SprocketsRenderer.new({})
end

CALLBACKS.each do |callback_name|
test "#render should pass prerender options to ##{callback_name}" do
mocked_method = MiniTest::Mock.new
mocked_method.expect :call, '', [
"Todo",
"{\"todo\":\"write tests\"}",
{ option: :value, render_function: "renderToString" }
]

@renderer.stub callback_name, mocked_method do
@renderer.render("Todo", { todo: "write tests" }, { option: :value })
end

mocked_method.verify
end
end

test '#render returns HTML' do
result = @renderer.render("Todo", {todo: "write tests"}, nil)
assert_match(/<li.*write tests<\/li>/, result)
Expand Down