Skip to content

Commit 2731a71

Browse files
author
Robert Mosolgo
committed
Merge pull request #221 from jakegavin/mount-unmount-at-node
Use a selector to mount and unmount components at a given node
2 parents 84a4148 + ea28c19 commit 2731a71

File tree

3 files changed

+38
-18
lines changed

3 files changed

+38
-18
lines changed

lib/assets/javascripts/react_ujs.js.erb

+17-12
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,14 @@
1212
RAILS_ENV_DEVELOPMENT: <%= Rails.env == "development" %>,
1313
// helper method for the mount and unmount methods to find the
1414
// `data-react-class` DOM elements
15-
findDOMNodes: function() {
15+
findDOMNodes: function(searchSelector) {
1616
// we will use fully qualified paths as we do not bind the callbacks
17-
var selector = '[' + window.ReactRailsUJS.CLASS_NAME_ATTR + ']';
17+
var selector;
18+
if (typeof searchSelector === 'undefined') {
19+
var selector = '[' + window.ReactRailsUJS.CLASS_NAME_ATTR + ']';
20+
} else {
21+
var selector = searchSelector + ' [' + window.ReactRailsUJS.CLASS_NAME_ATTR + ']';
22+
}
1823

1924
if ($) {
2025
return $(selector);
@@ -23,8 +28,8 @@
2328
}
2429
},
2530

26-
mountComponents: function() {
27-
var nodes = window.ReactRailsUJS.findDOMNodes();
31+
mountComponents: function(searchSelector) {
32+
var nodes = window.ReactRailsUJS.findDOMNodes(searchSelector);
2833

2934
for (var i = 0; i < nodes.length; ++i) {
3035
var node = nodes[i];
@@ -40,8 +45,8 @@
4045
}
4146
},
4247

43-
unmountComponents: function() {
44-
var nodes = window.ReactRailsUJS.findDOMNodes();
48+
unmountComponents: function(searchSelector) {
49+
var nodes = window.ReactRailsUJS.findDOMNodes(searchSelector);
4550

4651
for (var i = 0; i < nodes.length; ++i) {
4752
var node = nodes[i];
@@ -77,17 +82,17 @@
7782
console.warn('The Turbolinks cache has been disabled (Turbolinks >= 2.4.0 is recommended). See https://github.com/reactjs/react-rails/issues/87 for more information.');
7883
}
7984
}
80-
handleEvent('page:change', window.ReactRailsUJS.mountComponents);
81-
handleEvent(unmountEvent, window.ReactRailsUJS.unmountComponents);
85+
handleEvent('page:change', function() {window.ReactRailsUJS.mountComponents()});
86+
handleEvent(unmountEvent, function() {window.ReactRailsUJS.unmountComponents()});
8287
}
8388

8489
function handleNativeEvents() {
8590
if ($) {
86-
$(window.ReactRailsUJS.mountComponents);
87-
$(window).unload(window.ReactRailsUJS.unmountComponents);
91+
$(function() {window.ReactRailsUJS.mountComponents()});
92+
$(window).unload(function() {window.ReactRailsUJS.unmountComponents()});
8893
} else {
89-
document.addEventListener('DOMContentLoaded', window.ReactRailsUJS.mountComponents);
90-
window.addEventListener('unload', window.ReactRailsUJS.unmountComponents);
94+
document.addEventListener('DOMContentLoaded', function() {window.ReactRailsUJS.mountComponents()});
95+
window.addEventListener('unload', function() {window.ReactRailsUJS.unmountComponents()});
9196
}
9297
}
9398

test/dummy/app/views/pages/show.html.erb

+5-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,8 @@
22
<li><%= link_to 'Alice', page_path(:id => 0) %></li>
33
<li><%= link_to 'Bob', page_path(:id => 1) %></li>
44
</ul>
5-
<%= react_component 'HelloMessage', :name => @name %>
5+
<div id='test-component'>
6+
<%= react_component 'HelloMessage', :name => @name %>
7+
</div>
8+
<a href='#' onClick="ReactRailsUJS.unmountComponents('#test-component')">Unmount at #test-component</a>
9+
<a href='#' onClick="ReactRailsUJS.mountComponents('#test-component')">Mount at #test-component</a>

test/view_helper_test.rb

+16-5
Original file line numberDiff line numberDiff line change
@@ -48,21 +48,21 @@ class ViewHelperTest < ActionDispatch::IntegrationTest
4848
assert html.include?('class="test"')
4949
assert html.include?('data-foo="1"')
5050
end
51-
51+
5252
test 'ujs object present on the global React object and has our methods' do
5353
visit '/pages/1'
5454
assert page.has_content?('Hello Bob')
55-
55+
5656
# the exposed ujs object is present
5757
ujs_present = page.evaluate_script('typeof ReactRailsUJS === "object";')
5858
assert_equal(ujs_present, true)
59-
59+
6060
# it contains the constants
6161
class_name_present = page.evaluate_script('ReactRailsUJS.CLASS_NAME_ATTR === "data-react-class";')
6262
assert_equal(class_name_present, true)
6363
props_present = page.evaluate_script('ReactRailsUJS.PROPS_ATTR === "data-react-props";')
6464
assert_equal(props_present, true)
65-
65+
6666
#it contains the methods
6767
find_dom_nodes_present = page.evaluate_script('typeof ReactRailsUJS.findDOMNodes === "function";')
6868
assert_equal(find_dom_nodes_present, true)
@@ -115,13 +115,24 @@ class ViewHelperTest < ActionDispatch::IntegrationTest
115115
assert page.has_content?('Hello Bob')
116116
end
117117

118+
test 'react_ujs can unount at node' do
119+
visit '/pages/1'
120+
assert page.has_content?('Hello Bob')
121+
122+
page.click_link 'Unmount at #test-component'
123+
assert page.has_no_content?('Hello Bob')
124+
125+
page.click_link 'Mount at #test-component'
126+
assert page.has_content?('Hello Bob')
127+
end
128+
118129
test 'react server rendering also gets mounted on client' do
119130
visit '/server/1'
120131
assert_match(/data-react-class=\"TodoList\"/, page.html)
121132
assert_match(/data-react-checksum/, page.html)
122133
assert_match(/yep/, page.find("#status").text)
123134
end
124-
135+
125136
test 'react server rendering does not include internal properties' do
126137
visit '/server/1'
127138
assert_no_match(/tag=/, page.html)

0 commit comments

Comments
 (0)