Skip to content

Commit 1c1ab82

Browse files
committed
Fix asset reloading in development mode
The renderer was using a memoized class variable to cache the concatinated react.js and components.js for server-side rendering. This meant that when you updated a component, the server-rendered version would not be refreshed. Since #setup! is called every time a watched file is updated, it seems like the natural place to reset the memozied string.
1 parent bff5d43 commit 1c1ab82

File tree

4 files changed

+62
-4
lines changed

4 files changed

+62
-4
lines changed

lib/react/rails/railtie.rb

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,15 @@ class Railtie < ::Rails::Railtie
5656
config.after_initialize do |app|
5757
# Server Rendering
5858
# Concat component_filenames together for server rendering
59-
app.config.react.components_js = app.config.react.component_filenames.map do |filename|
60-
app.assets[filename].to_s
61-
end.join(";")
59+
app.config.react.components_js = lambda {
60+
app.config.react.component_filenames.map do |filename|
61+
app.assets[filename].to_s
62+
end.join(";")
63+
}
6264

6365
do_setup = lambda do
6466
cfg = app.config.react
65-
React::Renderer.setup!( cfg.react_js.call, cfg.components_js,
67+
React::Renderer.setup!( cfg.react_js.call, cfg.components_js.call,
6668
{:size => cfg.size, :timeout => cfg.timeout})
6769
end
6870

lib/react/renderer.rb

Lines changed: 1 addition & 0 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+
@@combined_js = nil if defined? @@combined_js
1314
@@pool = ConnectionPool.new(:size => args[:size]||10, :timeout => args[:timeout]||20) { self.new }
1415
end
1516

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/server_rendered_html_test.rb

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
require 'test_helper'
2+
require 'fileutils'
3+
4+
class ServerRenderedHtmlTest < ActionDispatch::IntegrationTest
5+
test 'react server rendering reloads jsx after changes to the jsx files' do
6+
file_with_updates = File.expand_path('../helper_files/TodoListWithUpdates.js.jsx', __FILE__)
7+
file_without_updates = File.expand_path('../helper_files/TodoListWithoutUpdates.js.jsx', __FILE__)
8+
app_file = File.expand_path('../dummy/app/assets/javascripts/components/TodoList.js.jsx', __FILE__)
9+
10+
sleep(1)
11+
FileUtils.cp app_file, file_without_updates
12+
# fixes inconsistent test runs; phantomjs doesn't always see that the file was
13+
# updated without manually calling #touch on it
14+
FileUtils.touch app_file
15+
16+
begin
17+
get '/server/1'
18+
refute_match 'Updated', response.body
19+
20+
sleep(1)
21+
FileUtils.cp file_with_updates, app_file
22+
FileUtils.touch app_file
23+
24+
get '/server/1'
25+
assert_match 'Updated', response.body
26+
ensure
27+
# if we have a test failure, we want to make sure that we revert the dummy file
28+
sleep(1)
29+
FileUtils.mv file_without_updates, app_file
30+
FileUtils.touch app_file
31+
end
32+
end
33+
end

0 commit comments

Comments
 (0)