Skip to content

Commit 65a26ba

Browse files
authored
Merge pull request #641 from prikha/master
#639 Pass pre-render options to callback functions
2 parents a23ab90 + 38acc6f commit 65a26ba

File tree

3 files changed

+78
-22
lines changed

3 files changed

+78
-22
lines changed

lib/react/server_rendering/exec_js_renderer.rb

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,10 @@ def initialize(options={})
1111
end
1212

1313
def render(component_name, props, prerender_options)
14-
render_function = prerender_options.fetch(:render_function, "renderToString")
15-
js_code = <<-JS
16-
(function () {
17-
#{before_render(component_name, props, prerender_options)}
18-
var result = ReactDOMServer.#{render_function}(React.createElement(#{component_name}, #{props}));
19-
#{after_render(component_name, props, prerender_options)}
20-
return result;
21-
})()
22-
JS
23-
@context.eval(js_code).html_safe
14+
js_executed_before = before_render(component_name, props, prerender_options)
15+
js_executed_after = after_render(component_name, props, prerender_options)
16+
js_main_section = main_render(component_name, props, prerender_options)
17+
render_from_parts(js_executed_before, js_main_section, js_executed_after)
2418
rescue ExecJS::ProgramError => err
2519
raise React::ServerRendering::PrerenderError.new(component_name, props, err)
2620
end
@@ -36,6 +30,28 @@ def after_render(component_name, props, prerender_options); ""; end
3630
var window = window || this;
3731
JS
3832

33+
private
34+
35+
def render_from_parts(before, main, after)
36+
js_code = compose_js(before, main, after)
37+
@context.eval(js_code).html_safe
38+
end
39+
40+
def main_render(component_name, props, prerender_options)
41+
render_function = prerender_options.fetch(:render_function, "renderToString")
42+
"ReactDOMServer.#{render_function}(React.createElement(#{component_name}, #{props}))"
43+
end
44+
45+
def compose_js(before, main, after)
46+
<<-JS
47+
(function () {
48+
#{before}
49+
var result = #{main};
50+
#{after}
51+
return result;
52+
})()
53+
JS
54+
end
3955
end
4056
end
4157
end

lib/react/server_rendering/sprockets_renderer.rb

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,14 @@ def initialize(options={})
2828
super(options.merge(code: js_code))
2929
end
3030

31+
# Prerender options are expected to be a Hash however might also be a symbol.
32+
# pass prerender: :static to use renderToStaticMarkup
33+
# pass prerender: true to enable default prerender
34+
# pass prerender: {} to proxy some custom options
3135
def render(component_name, props, prerender_options)
32-
# pass prerender: :static to use renderToStaticMarkup
33-
react_render_method = if prerender_options == :static
34-
"renderToStaticMarkup"
35-
else
36-
"renderToString"
37-
end
38-
39-
if !props.is_a?(String)
40-
props = props.to_json
41-
end
42-
43-
super(component_name, props, {render_function: react_render_method})
36+
t_options = prepare_options(prerender_options)
37+
t_props = prepare_props(props)
38+
super(component_name, t_props, t_options)
4439
end
4540

4641
def after_render(component_name, props, prerender_options)
@@ -76,6 +71,32 @@ def asset_container
7671
def assets_precompiled?
7772
!::Rails.application.config.assets.compile
7873
end
74+
75+
private
76+
77+
def prepare_options(options)
78+
r_func = render_function(options)
79+
opts = case options
80+
when Hash then options
81+
when TrueClass then {}
82+
else
83+
{}
84+
end
85+
# This seems redundant to pass
86+
opts.merge(render_function: r_func)
87+
end
88+
89+
def render_function(opts)
90+
if opts == :static
91+
'renderToStaticMarkup'.freeze
92+
else
93+
'renderToString'.freeze
94+
end
95+
end
96+
97+
def prepare_props(props)
98+
props.is_a?(String) ? props : props.to_json
99+
end
79100
end
80101
end
81102
end

test/react/server_rendering/sprockets_renderer_test.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,29 @@
22

33
when_sprockets_available do
44
class SprocketsRendererTest < ActiveSupport::TestCase
5+
CALLBACKS = [:before_render, :after_render]
6+
57
setup do
68
@renderer = React::ServerRendering::SprocketsRenderer.new({})
79
end
810

11+
CALLBACKS.each do |callback_name|
12+
test "#render should pass prerender options to ##{callback_name}" do
13+
mocked_method = MiniTest::Mock.new
14+
mocked_method.expect :call, '', [
15+
"Todo",
16+
"{\"todo\":\"write tests\"}",
17+
{ option: :value, render_function: "renderToString" }
18+
]
19+
20+
@renderer.stub callback_name, mocked_method do
21+
@renderer.render("Todo", { todo: "write tests" }, { option: :value })
22+
end
23+
24+
mocked_method.verify
25+
end
26+
end
27+
928
test '#render returns HTML' do
1029
result = @renderer.render("Todo", {todo: "write tests"}, nil)
1130
assert_match(/<li.*write tests<\/li>/, result)

0 commit comments

Comments
 (0)