From ea3c7b345bc69312e5e23361f56645de3bc45102 Mon Sep 17 00:00:00 2001 From: Michael Baudino Date: Wed, 1 Jun 2016 09:57:13 +0400 Subject: [PATCH] Fix `dom_id` collisions by using a UUID rather than an autoincremented index. This ensures that all DOM nodes ids are unique when multiple instances of a component co-exist on the same page. It also allows fragment caching of generated HTML (since the unicity does not depend on other components on the page). :warning: one must use the `id` parameter of `react_component` to force the generated DOM node id in order to have a predictable one (_e.g._ in tests). This commit also includes the CHANGELOG update and the version bump. Solves #437 --- CHANGELOG.md | 4 +++ README.md | 2 +- app/helpers/react_on_rails_helper.rb | 11 +------ lib/react_on_rails/react_component/options.rb | 11 +++---- lib/react_on_rails/version.rb | 2 +- package.json | 2 +- .../pages/client_side_hello_world.html.erb | 4 +-- ...ent_side_hello_world_shared_store.html.erb | 8 ++--- ...llo_world_shared_store_controller.html.erb | 8 ++--- ...de_hello_world_shared_store_defer.html.erb | 8 ++--- .../pages/client_side_log_throw.html.erb | 2 +- spec/dummy/app/views/pages/index.html.erb | 24 +++++++------- .../app/views/pages/pure_component.html.erb | 5 +-- .../pages/server_side_hello_world.html.erb | 4 +-- .../server_side_hello_world_es5.html.erb | 4 +-- ...ver_side_hello_world_shared_store.html.erb | 8 ++--- ...llo_world_shared_store_controller.html.erb | 8 ++--- ...de_hello_world_shared_store_defer.html.erb | 8 ++--- .../pages/server_side_log_throw.html.erb | 2 +- .../server_side_log_throw_raise.html.erb | 2 +- .../pages/server_side_redux_app.html.erb | 4 +-- .../server_side_redux_app_cached.html.erb | 4 +-- .../helpers/react_on_rails_helper_spec.rb | 2 ++ .../react_component/options_spec.rb | 32 +++++++------------ 24 files changed, 78 insertions(+), 91 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a2f662ef3..c51af7fdf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. Items under Contributors: please follow the recommendations outlined at [keepachangelog.com](http://keepachangelog.com/). Please use the existing headings and styling as a guide, and add a link for the version diff at the bottom of the file. Also, please update the `Unreleased` link to compare to the latest release version. ## [Unreleased] +## [6.0.2] +##### Fixed +- Fix colisions in ids of DOM nodes generated by `react_component` by indexing in using an UUID rather than an auto-increment value. This means that it should be overriden using the `id` parameter of `react_component` if one wants to generate a predictable id (_e.g._ for testing purpose). See [Issue #437](https://github.com/shakacode/react_on_rails/issues/437). Fixed in [#438](https://github.com/shakacode/react_on_rails/pull/438) by [Michael Baudino](https://github.com/michaelbaudino). + ## [6.0.1] ##### Fixed - Allow for older version of manifest.json for older versions of sprockets. See [Issue #435](https://github.com/shakacode/react_on_rails/issues/435). Fixed in [#436](https://github.com/shakacode/react_on_rails/pull/436) by [alleycat-at-git](https://github.com/alleycat-at-git). diff --git a/README.md b/README.md index c3d6b49df..6a68aac0b 100644 --- a/README.md +++ b/README.md @@ -306,7 +306,7 @@ react_component(component_name, + **options:** + **props:** Ruby Hash which contains the properties to pass to the react object, or a JSON string. If you pass a string, we'll escape it for you. + **prerender:** enable server-side rendering of component. Set to false when debugging! - + **id:** Id for the div. This will get assigned automatically if you do not provide an id. + + **id:** Id for the div, will be used to attach the React component. This will get assigned automatically if you do not provide an id. Must be unique. + **html_options:** Any other html options to get placed on the added div for the component. + **trace:** set to true to print additional debugging information in the browser. Defaults to true for development, off otherwise. Note, on the client you will so both the railsContext and your props. On the server, you only see the railsContext being logged. + **replay_console:** Default is true. False will disable echoing server-rendering logs to the browser. While this can make troubleshooting server rendering difficult, so long as you have the default configuration of logging_on_server set to true, you'll still see the errors on the server. diff --git a/app/helpers/react_on_rails_helper.rb b/app/helpers/react_on_rails_helper.rb index 9ebb15dca..a1efc4f3c 100644 --- a/app/helpers/react_on_rails_helper.rb +++ b/app/helpers/react_on_rails_helper.rb @@ -95,12 +95,8 @@ def react_component(component_name, raw_options = {}) # Create the JavaScript setup of the global to initialize the client rendering # (re-hydrate the data). This enables react rendered on the client to see that the # server has already rendered the HTML. - # We use this react_component_index in case we have the same component multiple times on the page. - react_component_index = next_react_component_index - options = ReactOnRails::ReactComponent::Options.new(name: component_name, - index: react_component_index, - options: raw_options) + options = ReactOnRails::ReactComponent::Options.new(name: component_name, options: raw_options) # Setup the page_loaded_js, which is the same regardless of prerendering or not! # The reason is that React is smart about not doing extra work if the server rendering did its job. @@ -253,11 +249,6 @@ def render_redux_store_data(redux_store_data) prepend_render_rails_context(result) end - def next_react_component_index - @react_component_index ||= -1 - @react_component_index += 1 - end - def props_string(props) props.is_a?(String) ? props : props.to_json end diff --git a/lib/react_on_rails/react_component/options.rb b/lib/react_on_rails/react_component/options.rb index cf6e7397f..54befc101 100644 --- a/lib/react_on_rails/react_component/options.rb +++ b/lib/react_on_rails/react_component/options.rb @@ -4,11 +4,8 @@ class Options NO_PROPS = {}.freeze HIDDEN = "display:none".freeze - attr_reader :index - - def initialize(name:, index:, options:) + def initialize(name:, options:) @name = name - @index = index @options = options end @@ -21,7 +18,7 @@ def name end def dom_id - options.fetch(:id) { default_dom_id } + @dom_id ||= options.fetch(:id) { generate_unique_dom_id } end def html_options @@ -62,8 +59,8 @@ def style attr_reader :options - def default_dom_id - "#{@name}-react-component-#{@index}" + def generate_unique_dom_id + "#{@name}-react-component-#{SecureRandom.uuid}" end def retrieve_key(key) diff --git a/lib/react_on_rails/version.rb b/lib/react_on_rails/version.rb index 4f7587738..c15bb6c32 100644 --- a/lib/react_on_rails/version.rb +++ b/lib/react_on_rails/version.rb @@ -1,4 +1,4 @@ # frozen_string_literal: true module ReactOnRails - VERSION = "6.0.1".freeze + VERSION = "6.0.2".freeze end diff --git a/package.json b/package.json index b126c8f82..909ddb52e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-on-rails", - "version": "6.0.1", + "version": "6.0.2", "description": "react-on-rails JavaScript for react_on_rails Ruby gem", "main": "node_package/lib/ReactOnRails.js", "directories": { diff --git a/spec/dummy/app/views/pages/client_side_hello_world.html.erb b/spec/dummy/app/views/pages/client_side_hello_world.html.erb index 602cae33e..b53c5da6e 100644 --- a/spec/dummy/app/views/pages/client_side_hello_world.html.erb +++ b/spec/dummy/app/views/pages/client_side_hello_world.html.erb @@ -1,5 +1,5 @@ <%= render "header" %> -<%= react_component("HelloWorld", props: @app_props_server_render, prerender: false, trace: true) %> +<%= react_component("HelloWorld", props: @app_props_server_render, prerender: false, trace: true, id: "HelloWorld-react-component-0") %>

React Rails Client Side Only Rendering

@@ -31,7 +31,7 @@ Place the component on the view: spec/dummy/app/views/pages/client_side_hello_world.html.erb
-      <%%= react_component("HelloWorld", props: @app_props_server_render, prerender: false, trace: true) %>
+      <%%= react_component("HelloWorld", props: @app_props_server_render, prerender: false, trace: true, id: "HelloWorld-react-component-0") %>
     
diff --git a/spec/dummy/app/views/pages/client_side_hello_world_shared_store.html.erb b/spec/dummy/app/views/pages/client_side_hello_world_shared_store.html.erb index ad92cbb29..6392c2fc1 100644 --- a/spec/dummy/app/views/pages/client_side_hello_world_shared_store.html.erb +++ b/spec/dummy/app/views/pages/client_side_hello_world_shared_store.html.erb @@ -1,10 +1,10 @@ <%= render "header" %> <%= redux_store("SharedReduxStore", props: @app_props_server_render) %> -<%= react_component("ReduxSharedStoreApp", prerender: false, trace: true) %> +<%= react_component("ReduxSharedStoreApp", prerender: false, trace: true, id: "ReduxSharedStoreApp-react-component-0") %>

Second Hello World

-<%= react_component("ReduxSharedStoreApp", prerender: false, trace: true) %> +<%= react_component("ReduxSharedStoreApp", prerender: false, trace: true, id: "ReduxSharedStoreApp-react-component-1") %>

React Rails Client Side Only Rendering, 2 components, same Redux store

@@ -30,10 +30,10 @@
 <%%= redux_store("SharedReduxStore", props: @app_props_server_render) %>
 
-<%%= react_component("ReduxSharedStoreApp", prerender: false, trace: true) %>
+<%%= react_component("ReduxSharedStoreApp", prerender: false, trace: true, id: "ReduxSharedStoreApp-react-component-0") %>
 
 Second Hello World
-<%%= react_component("ReduxSharedStoreApp", prerender: false, trace: true) %>
+<%%= react_component("ReduxSharedStoreApp", prerender: false, trace: true, id: "ReduxSharedStoreApp-react-component-1") %>
     
diff --git a/spec/dummy/app/views/pages/client_side_hello_world_shared_store_controller.html.erb b/spec/dummy/app/views/pages/client_side_hello_world_shared_store_controller.html.erb index adab0e8a6..3bbf46fa1 100644 --- a/spec/dummy/app/views/pages/client_side_hello_world_shared_store_controller.html.erb +++ b/spec/dummy/app/views/pages/client_side_hello_world_shared_store_controller.html.erb @@ -1,9 +1,9 @@ <%= render "header" %> -<%= react_component("ReduxSharedStoreApp", prerender: false, trace: true) %> +<%= react_component("ReduxSharedStoreApp", prerender: false, trace: true, id: "ReduxSharedStoreApp-react-component-0") %>

Second Hello World

-<%= react_component("ReduxSharedStoreApp", prerender: false, trace: true) %> +<%= react_component("ReduxSharedStoreApp", prerender: false, trace: true, id: "ReduxSharedStoreApp-react-component-1") %>

React Rails Client Side Only Rendering, 2 components, same Redux store

@@ -29,10 +29,10 @@
 <%%= redux_store("SharedReduxStore", props: @app_props_server_render) %>
 
-<%%= react_component("ReduxSharedStoreApp", prerender: false, trace: true) %>
+<%%= react_component("ReduxSharedStoreApp", prerender: false, trace: true, id: "ReduxSharedStoreApp-react-component-0") %>
 
 Second Hello World
-<%%= react_component("ReduxSharedStoreApp", prerender: false, trace: true) %>
+<%%= react_component("ReduxSharedStoreApp", prerender: false, trace: true, id: "ReduxSharedStoreApp-react-component-1") %>
     
diff --git a/spec/dummy/app/views/pages/client_side_hello_world_shared_store_defer.html.erb b/spec/dummy/app/views/pages/client_side_hello_world_shared_store_defer.html.erb index 85b1d44ab..3d062990b 100644 --- a/spec/dummy/app/views/pages/client_side_hello_world_shared_store_defer.html.erb +++ b/spec/dummy/app/views/pages/client_side_hello_world_shared_store_defer.html.erb @@ -3,10 +3,10 @@ YO <% redux_store("SharedReduxStore", props: @app_props_server_render, defer: true) %> -<%= react_component("ReduxSharedStoreApp", prerender: false, trace: true) %> +<%= react_component("ReduxSharedStoreApp", prerender: false, trace: true, id: "ReduxSharedStoreApp-react-component-0") %>

Second Hello World

-<%= react_component("ReduxSharedStoreApp", prerender: false, trace: true) %> +<%= react_component("ReduxSharedStoreApp", prerender: false, trace: true, id: "ReduxSharedStoreApp-react-component-1") %>

React Rails Client Side Only Rendering, 2 components, same Redux store

@@ -32,10 +32,10 @@ YO
 <%%= redux_store("SharedReduxStore", props: @app_props_server_render) %>
 
-<%%= react_component("ReduxSharedStoreApp", prerender: false, trace: true) %>
+<%%= react_component("ReduxSharedStoreApp", prerender: false, trace: true, id: "ReduxSharedStoreApp-react-component-0") %>
 
 Second Hello World
-<%%= react_component("ReduxSharedStoreApp", prerender: false, trace: true) %>
+<%%= react_component("ReduxSharedStoreApp", prerender: false, trace: true, id: "ReduxSharedStoreApp-react-component-1") %>
     
diff --git a/spec/dummy/app/views/pages/client_side_log_throw.html.erb b/spec/dummy/app/views/pages/client_side_log_throw.html.erb index 140a7aafb..34019a4e6 100644 --- a/spec/dummy/app/views/pages/client_side_log_throw.html.erb +++ b/spec/dummy/app/views/pages/client_side_log_throw.html.erb @@ -1,7 +1,7 @@ <%= render "header" %> <%= react_component("HelloWorldWithLogAndThrow", props: @app_props_server_render, - prerender: false, trace: true) %> + prerender: false, trace: true, id: "HelloWorldWithLogAndThrow-react-component-0") %>

React Rails Client Rendering

diff --git a/spec/dummy/app/views/pages/index.html.erb b/spec/dummy/app/views/pages/index.html.erb index ddd7601e2..24b58c3ad 100644 --- a/spec/dummy/app/views/pages/index.html.erb +++ b/spec/dummy/app/views/pages/index.html.erb @@ -23,7 +23,7 @@ This page demonstrates a few things the other pages do not show:
   <%% cache @app_props_server_render do %>
- <%%= react_component("ReduxApp", props: @app_props_server_render, trace: true) %>
+ <%%= react_component("ReduxApp", props: @app_props_server_render, trace: true, id: "ReduxApp-react-component-0") %>
<%% end %>

@@ -36,13 +36,13 @@ This page demonstrates a few things the other pages do not show: <% puts "server rendering react components" %> <% puts "=" * 80 %> <% end %> - <%= react_component("ReduxApp", props: @app_props_server_render, trace: true) %> + <%= react_component("ReduxApp", props: @app_props_server_render, trace: true, id: "ReduxApp-react-component-0") %>


Server Rendered/Cached React Component Without Redux

     <%% cache @app_props_server_render do %>
- <%%= react_component("HelloWorld", props: @app_props_server_render, trace: true) %>
+ <%%= react_component("HelloWorld", props: @app_props_server_render, trace: true, id: "HelloWorld-react-component-1") %>
<%% end %>

@@ -50,32 +50,32 @@ This page demonstrates a few things the other pages do not show: Note, that we don't suffix the component name with "App"

- <%= react_component("HelloWorld", props: @app_props_server_render, trace: true) %> + <%= react_component("HelloWorld", props: @app_props_server_render, trace: true, id: "HelloWorld-react-component-1") %> <% end %>

Simple Client Rendered Component

-  <%%= react_component("HelloWorldApp", props: @app_props_hello, prerender: false, trace: true) %>
+  <%%= react_component("HelloWorldApp", props: @app_props_hello, prerender: false, trace: true, id: "HelloWorldApp-react-component-2") %>
 
-<%= react_component("HelloWorldApp", props: @app_props_hello, prerender: false, trace: true) %> +<%= react_component("HelloWorldApp", props: @app_props_hello, prerender: false, trace: true, id: "HelloWorldApp-react-component-2") %>

Showing you can put the same component twice on a page with different props

-  <%%= react_component("HelloWorldApp", props: @app_props_hello_again, prerender: false, trace: true) %>
+  <%%= react_component("HelloWorldApp", props: @app_props_hello_again, prerender: false, trace: true, id: "HelloWorldApp-react-component-3") %>
 
-<%= react_component("HelloWorldApp", props: @app_props_hello_again, prerender: false, trace: true) %> +<%= react_component("HelloWorldApp", props: @app_props_hello_again, prerender: false, trace: true, id: "HelloWorldApp-react-component-3") %>

Simple Component Without Redux

-  <%%= react_component("HelloWorld", props: @app_props_hello, prerender: false, trace: true) %>
-  <%%= react_component("HelloES5", props: @app_props_hello, prerender: false, trace: true) %>
+  <%%= react_component("HelloWorld", props: @app_props_hello, prerender: false, trace: true, id: "HelloWorld-react-component-4") %>
+  <%%= react_component("HelloES5", props: @app_props_hello, prerender: false, trace: true, id: "HelloES5-react-component-5") %>
 
-<%= react_component("HelloWorld", props: @app_props_hello, prerender: false, trace: true) %> -<%= react_component("HelloWorldES5", props: @app_props_hello, prerender: false, trace: true) %> +<%= react_component("HelloWorld", props: @app_props_hello, prerender: false, trace: true, id: "HelloWorld-react-component-4") %> +<%= react_component("HelloWorldES5", props: @app_props_hello, prerender: false, trace: true, id: "HelloWorldES5-react-component-5") %>

Non-React Component

diff --git a/spec/dummy/app/views/pages/pure_component.html.erb b/spec/dummy/app/views/pages/pure_component.html.erb index f835e4f0c..a137f7834 100644 --- a/spec/dummy/app/views/pages/pure_component.html.erb +++ b/spec/dummy/app/views/pages/pure_component.html.erb @@ -1,6 +1,6 @@ <%= render "header" %> -<%= react_component("PureComponent", props: { title: "This is a Pure Component!" }, prerender: true, trace: true) %> +<%= react_component("PureComponent", props: { title: "This is a Pure Component!" }, prerender: true, trace: true, id: "PureComponent-react-component-0") %>
@@ -9,5 +9,6 @@ <%%= react_component("PureComponent", { title: "This is a Pure Component!" }, prerender: true, - trace: true) %> + trace: true, + id: "PureComponent-react-component-0") %> diff --git a/spec/dummy/app/views/pages/server_side_hello_world.html.erb b/spec/dummy/app/views/pages/server_side_hello_world.html.erb index 510f224ce..8a863a47e 100644 --- a/spec/dummy/app/views/pages/server_side_hello_world.html.erb +++ b/spec/dummy/app/views/pages/server_side_hello_world.html.erb @@ -1,6 +1,6 @@ <%= render "header" %> -<%= react_component("HelloWorld", props: @app_props_server_render, prerender: true, trace: true) %> +<%= react_component("HelloWorld", props: @app_props_server_render, prerender: true, trace: true, id: "HelloWorld-react-component-0") %>

React Rails Server Rendering

@@ -66,7 +66,7 @@ Place the component on the view: spec/dummy/app/views/pages/client_side_hello_world.html.erb
-    <%%= react_component("HelloWorld", props: @app_props_server_render, prerender: true, trace: true) %>
+    <%%= react_component("HelloWorld", props: @app_props_server_render, prerender: true, trace: true, id: "HelloWorld-react-component-0") %>
     
diff --git a/spec/dummy/app/views/pages/server_side_hello_world_es5.html.erb b/spec/dummy/app/views/pages/server_side_hello_world_es5.html.erb index a66f6b0eb..9e6fdfbb9 100644 --- a/spec/dummy/app/views/pages/server_side_hello_world_es5.html.erb +++ b/spec/dummy/app/views/pages/server_side_hello_world_es5.html.erb @@ -1,5 +1,5 @@ <%= render "header" %> -<%= react_component("HelloWorldES5", props: @app_props_server_render, prerender: true, trace: true) %> +<%= react_component("HelloWorldES5", props: @app_props_server_render, prerender: true, trace: true, id: "HelloWorldES5-react-component-0") %>

React Rails Server Rendering ES5 Style React.createClass

@@ -34,7 +34,7 @@ Place the component on the view: spec/dummy/app/views/pages/client_side_hello_world.html.erb

-      <%%= react_component("HelloWorldES5", props: @app_props_server_render, prerender: true, trace: true) %>
+      <%%= react_component("HelloWorldES5", props: @app_props_server_render, prerender: true, trace: true, id: "HelloWorldES5-react-component-0") %>
     
diff --git a/spec/dummy/app/views/pages/server_side_hello_world_shared_store.html.erb b/spec/dummy/app/views/pages/server_side_hello_world_shared_store.html.erb index c333871f6..5727a4870 100644 --- a/spec/dummy/app/views/pages/server_side_hello_world_shared_store.html.erb +++ b/spec/dummy/app/views/pages/server_side_hello_world_shared_store.html.erb @@ -1,10 +1,10 @@ <%= render "header" %> <%= redux_store("SharedReduxStore", props: @app_props_server_render) %> -<%= react_component("ReduxSharedStoreApp", prerender: true, trace: true) %> +<%= react_component("ReduxSharedStoreApp", prerender: true, trace: true, id: "ReduxSharedStoreApp-react-component-0") %>

Second Hello World

-<%= react_component("ReduxSharedStoreApp", prerender: true, trace: true) %> +<%= react_component("ReduxSharedStoreApp", prerender: true, trace: true, id: "ReduxSharedStoreApp-react-component-1") %>

React Rails Client Side Only Rendering, 2 components, same Redux store

@@ -30,10 +30,10 @@
 <%%= redux_store("SharedReduxStore", props: @app_props_server_render) %>
 
-<%%= react_component("ReduxSharedStoreApp", prerender: false, trace: true) %>
+<%%= react_component("ReduxSharedStoreApp", prerender: false, trace: true, id: "ReduxSharedStoreApp-react-component-0") %>
 
 Second Hello World
-<%%= react_component("ReduxSharedStoreApp", prerender: false, trace: true) %>
+<%%= react_component("ReduxSharedStoreApp", prerender: false, trace: true, id: "ReduxSharedStoreApp-react-component-1") %>
     
diff --git a/spec/dummy/app/views/pages/server_side_hello_world_shared_store_controller.html.erb b/spec/dummy/app/views/pages/server_side_hello_world_shared_store_controller.html.erb index ae2732717..511cdbeab 100644 --- a/spec/dummy/app/views/pages/server_side_hello_world_shared_store_controller.html.erb +++ b/spec/dummy/app/views/pages/server_side_hello_world_shared_store_controller.html.erb @@ -1,9 +1,9 @@ <%= render "header" %> -<%= react_component("ReduxSharedStoreApp", prerender: true, trace: true) %> +<%= react_component("ReduxSharedStoreApp", prerender: true, trace: true, id: "ReduxSharedStoreApp-react-component-0") %>

Second Hello World

-<%= react_component("ReduxSharedStoreApp", prerender: true, trace: true) %> +<%= react_component("ReduxSharedStoreApp", prerender: true, trace: true, id: "ReduxSharedStoreApp-react-component-1") %>

React Rails Client Side Only Rendering, 2 components, same Redux store from controller

@@ -36,10 +36,10 @@ redux_store("SharedReduxStore", props: @app_props_server_render) Place the components: spec/dummy/app/views/pages/server_side_hello_world_shared_store_controller.html.erb
-<%%= react_component("ReduxSharedStoreApp", prerender: false, trace: true) %>
+<%%= react_component("ReduxSharedStoreApp", prerender: false, trace: true, id: "ReduxSharedStoreApp-react-component-0") %>
 
 Second Hello World
-<%%= react_component("ReduxSharedStoreApp", prerender: false, trace: true) %>
+<%%= react_component("ReduxSharedStoreApp", prerender: false, trace: true, id: "ReduxSharedStoreApp-react-component-1") %>
     
diff --git a/spec/dummy/app/views/pages/server_side_hello_world_shared_store_defer.html.erb b/spec/dummy/app/views/pages/server_side_hello_world_shared_store_defer.html.erb index c601b6074..12b1722bf 100644 --- a/spec/dummy/app/views/pages/server_side_hello_world_shared_store_defer.html.erb +++ b/spec/dummy/app/views/pages/server_side_hello_world_shared_store_defer.html.erb @@ -1,10 +1,10 @@ <%= render "header" %> <% redux_store("SharedReduxStore", props: @app_props_server_render, defer: true) %> -<%= react_component("ReduxSharedStoreApp", prerender: true, trace: true) %> +<%= react_component("ReduxSharedStoreApp", prerender: true, trace: true, id: "ReduxSharedStoreApp-react-component-0") %>

Second Hello World

-<%= react_component("ReduxSharedStoreApp", prerender: true, trace: true) %> +<%= react_component("ReduxSharedStoreApp", prerender: true, trace: true, id: "ReduxSharedStoreApp-react-component-1") %>

React Rails Client Side Only Rendering, 2 components, same Redux store

@@ -30,10 +30,10 @@
 <%%= redux_store("SharedReduxStore", props: @app_props_server_render, defer: true) %>
 
-<%%= react_component("ReduxSharedStoreApp", prerender: false, trace: true) %>
+<%%= react_component("ReduxSharedStoreApp", prerender: false, trace: true, id: "ReduxSharedStoreApp-react-component-0") %>
 
 Second Hello World
-<%%= react_component("ReduxSharedStoreApp", prerender: false, trace: true) %>
+<%%= react_component("ReduxSharedStoreApp", prerender: false, trace: true, id: "ReduxSharedStoreApp-react-component-1") %>
     
diff --git a/spec/dummy/app/views/pages/server_side_log_throw.html.erb b/spec/dummy/app/views/pages/server_side_log_throw.html.erb index 1943aa2f0..e2d156650 100644 --- a/spec/dummy/app/views/pages/server_side_log_throw.html.erb +++ b/spec/dummy/app/views/pages/server_side_log_throw.html.erb @@ -1,6 +1,6 @@ <%= render "header" %> -<%= react_component("HelloWorldWithLogAndThrow", props: @app_props_server_render, prerender: true, trace: true) %> +<%= react_component("HelloWorldWithLogAndThrow", props: @app_props_server_render, prerender: true, trace: true, id: "HelloWorldWithLogAndThrow-react-component-0") %>

React Rails Server Rendering

diff --git a/spec/dummy/app/views/pages/server_side_log_throw_raise.html.erb b/spec/dummy/app/views/pages/server_side_log_throw_raise.html.erb index e4a142ffc..215dbfb4d 100644 --- a/spec/dummy/app/views/pages/server_side_log_throw_raise.html.erb +++ b/spec/dummy/app/views/pages/server_side_log_throw_raise.html.erb @@ -3,4 +3,4 @@ Next line will throw on the server side because raise_on_prerender_error is true <%= react_component("HelloWorldWithLogAndThrow", props: @app_props_server_render, prerender: true, - trace: true, raise_on_prerender_error: true) %> + trace: true, raise_on_prerender_error: true, id: "HelloWorldWithLogAndThrow-react-component-0") %> diff --git a/spec/dummy/app/views/pages/server_side_redux_app.html.erb b/spec/dummy/app/views/pages/server_side_redux_app.html.erb index 85a034107..489263b63 100644 --- a/spec/dummy/app/views/pages/server_side_redux_app.html.erb +++ b/spec/dummy/app/views/pages/server_side_redux_app.html.erb @@ -1,6 +1,6 @@ <%= render "header" %> -<%= react_component("ReduxApp", props: @app_props_server_render, prerender: true, trace: true) %> +<%= react_component("ReduxApp", props: @app_props_server_render, prerender: true, trace: true, id: "ReduxApp-react-component-0") %>

Server Rendered/Cached React/Redux Component

@@ -55,7 +55,7 @@ Place the component on the view: spec/dummy/app/views/pages/server_side_redux_app.html.erb
-    <%%= react_component("ReduxApp", props: @app_props_server_render, prerender: true, trace: true) %>
+    <%%= react_component("ReduxApp", props: @app_props_server_render, prerender: true, trace: true, id: "ReduxApp-react-component-0") %>
     
diff --git a/spec/dummy/app/views/pages/server_side_redux_app_cached.html.erb b/spec/dummy/app/views/pages/server_side_redux_app_cached.html.erb index bef81215e..40b174f60 100644 --- a/spec/dummy/app/views/pages/server_side_redux_app_cached.html.erb +++ b/spec/dummy/app/views/pages/server_side_redux_app_cached.html.erb @@ -5,7 +5,7 @@ <% puts "=" * 80 %> <% puts "server rendering react components" %> <% puts "=" * 80 %> - <%= react_component("ReduxApp", props: @app_props_server_render, prerender: true, trace: true) %> + <%= react_component("ReduxApp", props: @app_props_server_render, prerender: true, trace: true, id: "ReduxApp-react-component-0") %> <% end %>
@@ -63,7 +63,7 @@
     <%% cache @app_props_server_render do %>
-      <%%= react_component("ReduxApp", props: @app_props_server_render, prerender: true, trace: true) %>
+      <%%= react_component("ReduxApp", props: @app_props_server_render, prerender: true, trace: true, id: "ReduxApp-react-component-0") %>
     <%% end %>
     
diff --git a/spec/dummy/spec/helpers/react_on_rails_helper_spec.rb b/spec/dummy/spec/helpers/react_on_rails_helper_spec.rb index fa6e92a5b..4889fd0ea 100644 --- a/spec/dummy/spec/helpers/react_on_rails_helper_spec.rb +++ b/spec/dummy/spec/helpers/react_on_rails_helper_spec.rb @@ -45,6 +45,8 @@ end describe "#react_component" do + before { allow(SecureRandom).to receive(:uuid).and_return(0, 1, 2, 3) } + subject { react_component("App", props: props) } let(:props) do diff --git a/spec/react_on_rails/react_component/options_spec.rb b/spec/react_on_rails/react_component/options_spec.rb index 3fea181cb..f5311a46c 100644 --- a/spec/react_on_rails/react_component/options_spec.rb +++ b/spec/react_on_rails/react_component/options_spec.rb @@ -8,10 +8,9 @@ raise_on_prerender_error ).freeze - def the_attrs(name: "App", index: 1, options: {}) + def the_attrs(name: "App", options: {}) { name: name, - index: index, options: options } end @@ -69,32 +68,25 @@ def the_attrs(name: "App", index: 1, options: {}) end end - describe "#index" do - it "returns index" do - index = 2 - attrs = the_attrs(index: index) - - opts = described_class.new(attrs) - - expect(opts.index).to eq index - end - end - describe "#dom_id" do context "without id option" do - it "returns dom_id" do - index = 2 - name = "some_app" - attrs = the_attrs(name: name, index: index) - + it "returns a unique identifier" do + attrs = the_attrs(name: "some_app") opts = described_class.new(attrs) - expect(opts.dom_id).to eq "some_app-react-component-2" + expect(SecureRandom).to receive(:uuid).and_return("123456789") + expect(opts.dom_id).to eq "some_app-react-component-123456789" + end + + it "is memoized" do + opts = described_class.new(the_attrs) + + expect(opts.dom_id).to eq opts.dom_id end end context "with id option" do - it "returns dom_id" do + it "returns given id" do options = { id: "im-an-id" } attrs = the_attrs(options: options)