Skip to content

Commit b4051e1

Browse files
committed
Merge pull request #59 from xionon/master
Fix server-side rendering in development mode
2 parents bfdb39f + 53256d1 commit b4051e1

File tree

7 files changed

+88
-8
lines changed

7 files changed

+88
-8
lines changed

lib/react/rails/railtie.rb

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,15 @@ class Railtie < ::Rails::Railtie
6363
config.after_initialize do |app|
6464
# Server Rendering
6565
# Concat component_filenames together for server rendering
66-
app.config.react.components_js = app.config.react.component_filenames.map do |filename|
67-
app.assets[filename].to_s
68-
end.join(";")
66+
app.config.react.components_js = lambda {
67+
app.config.react.component_filenames.map do |filename|
68+
app.assets[filename].to_s
69+
end.join(";")
70+
}
6971

7072
do_setup = lambda do
7173
cfg = app.config.react
72-
React::Renderer.setup!( cfg.react_js.call, cfg.components_js,
74+
React::Renderer.setup!( cfg.react_js, cfg.components_js,
7375
{:size => cfg.size, :timeout => cfg.timeout})
7476
end
7577

lib/react/renderer.rb

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ def self.setup!(react_js, components_js, args={})
1010
@@react_js = react_js
1111
@@components_js = components_js
1212
@@pool.shutdown{} if @@pool
13+
reset_combined_js!
1314
@@pool = ConnectionPool.new(:size => args[:size]||10, :timeout => args[:timeout]||20) { self.new }
1415
end
1516

@@ -19,8 +20,8 @@ def self.render(component, args={})
1920
end
2021
end
2122

22-
def self.combined_js
23-
@@combined_js ||= <<-CODE
23+
def self.setup_combined_js
24+
<<-CODE
2425
var global = global || this;
2526
2627
var console = global.console || {};
@@ -30,12 +31,20 @@ def self.combined_js
3031
}
3132
});
3233
33-
#{@@react_js};
34+
#{@@react_js.call};
3435
React = global.React;
35-
#{@@components_js};
36+
#{@@components_js.call};
3637
CODE
3738
end
3839

40+
def self.reset_combined_js!
41+
@@combined_js = setup_combined_js
42+
end
43+
44+
def self.combined_js
45+
@@combined_js
46+
end
47+
3948
def context
4049
@context ||= ExecJS.compile(self.class.combined_js)
4150
end
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/** @jsx React.DOM */
2+
3+
TodoList = React.createClass({
4+
getInitialState: function() {
5+
return({mounted: "nope"});
6+
},
7+
componentWillMount: function() {
8+
this.setState({mounted: 'yep'});
9+
},
10+
render: function() {
11+
return (
12+
<ul>
13+
<li>Updated</li>
14+
<li id='status'>{this.state.mounted}</li>
15+
{this.props.todos.map(function(todo, i) {
16+
return (<Todo key={i} todo={todo} />)
17+
})}
18+
</ul>
19+
)
20+
}
21+
})
22+

test/react_test.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ class ReactTest < ActionDispatch::IntegrationTest
3131

3232
assert_response :success
3333
assert_equal "'test_confirmation_token_react_content';\n", @response.body
34+
35+
React::Renderer.reset_combined_js!
3436
end
3537

3638
end

test/server_rendered_html_test.rb

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
require 'test_helper'
2+
require 'fileutils'
3+
4+
class ServerRenderedHtmlTest < ActionDispatch::IntegrationTest
5+
# Rails' asset pipeline has trouble picking up changes to files if they happen too fast.
6+
# By sleeping for a little bit at certain points, we can make sure that rails notices the
7+
# change in the file mtime, and calls our renderer setup functions appropriately
8+
def wait_to_ensure_asset_pipeline_detects_changes
9+
sleep(1)
10+
end
11+
12+
test 'react server rendering reloads jsx after changes to the jsx files' do
13+
file_with_updates = File.expand_path('../helper_files/TodoListWithUpdates.js.jsx', __FILE__)
14+
file_without_updates = File.expand_path('../helper_files/TodoListWithoutUpdates.js.jsx', __FILE__)
15+
app_file = File.expand_path('../dummy/app/assets/javascripts/components/TodoList.js.jsx', __FILE__)
16+
17+
FileUtils.cp app_file, file_without_updates
18+
FileUtils.touch app_file
19+
20+
begin
21+
get '/server/1'
22+
refute_match 'Updated', response.body
23+
24+
wait_to_ensure_asset_pipeline_detects_changes
25+
FileUtils.cp file_with_updates, app_file
26+
FileUtils.touch app_file
27+
28+
get '/server/1'
29+
assert_match 'Updated', response.body
30+
ensure
31+
# if we have a test failure, we want to make sure that we revert the dummy file
32+
wait_to_ensure_asset_pipeline_detects_changes
33+
FileUtils.mv file_without_updates, app_file
34+
FileUtils.touch app_file
35+
end
36+
end
37+
end

test/test_helper.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,7 @@
2222
if ActiveSupport::TestCase.method_defined?(:fixture_path=)
2323
ActiveSupport::TestCase.fixture_path = File.expand_path("../fixtures", __FILE__)
2424
end
25+
26+
def wait_for_turbolinks_to_be_available
27+
sleep(1)
28+
end

test/view_helper_test.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,14 @@ class ViewHelperTest < ActionDispatch::IntegrationTest
6262
page.execute_script('history.back();')
6363
assert page.has_content?('Hello Alice')
6464

65+
wait_for_turbolinks_to_be_available()
66+
6567
# Try Turbolinks javascript API.
6668
page.execute_script('Turbolinks.visit("/pages/2");')
6769
assert page.has_content?('Hello Alice')
6870

71+
wait_for_turbolinks_to_be_available()
72+
6973
page.execute_script('Turbolinks.visit("/pages/1");')
7074
assert page.has_content?('Hello Bob')
7175

0 commit comments

Comments
 (0)