From 3ae34e11dab76b15d07dbf08a86ab9d08c740ef9 Mon Sep 17 00:00:00 2001 From: dphaener Date: Sat, 12 Mar 2016 16:59:03 -0800 Subject: [PATCH 1/5] Update to accept new babel 6 module exports With the update to Babel 6, modules are being exported differently. For instance, the default module is now under a default key. This is breaking things when using an expose loader with webpack. This adds a check for that before trying to import the module. --- lib/assets/javascripts/react_ujs_mount.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/assets/javascripts/react_ujs_mount.js b/lib/assets/javascripts/react_ujs_mount.js index f95577682..664be9e16 100644 --- a/lib/assets/javascripts/react_ujs_mount.js +++ b/lib/assets/javascripts/react_ujs_mount.js @@ -53,7 +53,7 @@ // Assume className is simple and can be found at top-level (window). // Fallback to eval to handle cases like 'My.React.ComponentName'. - var constructor = window[className] || eval.call(window, className); + var constructor = window[className].default || window[className] || eval.call(window, className); var propsJson = node.getAttribute(window.ReactRailsUJS.PROPS_ATTR); var props = propsJson && JSON.parse(propsJson); From 554de3cbe216c385dba78f87c64ed36d819f588b Mon Sep 17 00:00:00 2001 From: dphaener Date: Fri, 29 Apr 2016 10:16:18 -0700 Subject: [PATCH 2/5] Update constructor getting to be more robust This uses @rmosolgo's suggestion for safely grabbing the class constructor from the window. It moves all of the logic into a private function that is called to set the constructor for each className. --- lib/assets/javascripts/react_ujs_mount.js | 30 ++++++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/lib/assets/javascripts/react_ujs_mount.js b/lib/assets/javascripts/react_ujs_mount.js index 664be9e16..57983fa14 100644 --- a/lib/assets/javascripts/react_ujs_mount.js +++ b/lib/assets/javascripts/react_ujs_mount.js @@ -2,6 +2,31 @@ // jQuery is optional. Use it to support legacy browsers. var $ = (typeof window.jQuery !== 'undefined') && window.jQuery; + // Get the constructor for a className + // Not a part of the public API + function getConstructor(className) { + // Assume className is simple and can be found at top-level (window). + // Fallback to eval to handle cases like 'My.React.ComponentName'. + // Also, try to gracefully import Babel 6 style default exports + // + var constructor; + + // Try to access the class globally first + constructor = window[className]; + + // If that didn't work, try eval + if (!constructor) { + constructor = eval.call(window, className)' + } + + // Lastly, if there is a default attribute try that + if (constructor && constructor.default) { + constructor = constructor.default; + } + + return constructor; + } + window.ReactRailsUJS = { // This attribute holds the name of component which should be mounted // example: `data-react-class="MyApp.Items.EditForm"` @@ -50,10 +75,7 @@ for (var i = 0; i < nodes.length; ++i) { var node = nodes[i]; var className = node.getAttribute(window.ReactRailsUJS.CLASS_NAME_ATTR); - - // Assume className is simple and can be found at top-level (window). - // Fallback to eval to handle cases like 'My.React.ComponentName'. - var constructor = window[className].default || window[className] || eval.call(window, className); + var constructor = getConstructor(className); var propsJson = node.getAttribute(window.ReactRailsUJS.PROPS_ATTR); var props = propsJson && JSON.parse(propsJson); From 4ee1b8fef8f1137215600a6e7db83cbc04fac434 Mon Sep 17 00:00:00 2001 From: dphaener Date: Fri, 29 Apr 2016 10:26:25 -0700 Subject: [PATCH 3/5] Fix small typo --- lib/assets/javascripts/react_ujs_mount.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/assets/javascripts/react_ujs_mount.js b/lib/assets/javascripts/react_ujs_mount.js index 57983fa14..17d5cf95a 100644 --- a/lib/assets/javascripts/react_ujs_mount.js +++ b/lib/assets/javascripts/react_ujs_mount.js @@ -16,7 +16,7 @@ // If that didn't work, try eval if (!constructor) { - constructor = eval.call(window, className)' + constructor = eval.call(window, className); } // Lastly, if there is a default attribute try that From d7674a2aab221cdc51af3f0de4ea662e5db9a643 Mon Sep 17 00:00:00 2001 From: dphaener Date: Fri, 29 Apr 2016 10:29:22 -0700 Subject: [PATCH 4/5] Move getConstructor function to public API This moves the getConstructor function into the public API, allowing anyone to override it if they have custom build behaviors that they need to account for. --- lib/assets/javascripts/react_ujs_mount.js | 26 ++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/lib/assets/javascripts/react_ujs_mount.js b/lib/assets/javascripts/react_ujs_mount.js index 17d5cf95a..4a5e8c861 100644 --- a/lib/assets/javascripts/react_ujs_mount.js +++ b/lib/assets/javascripts/react_ujs_mount.js @@ -67,6 +67,30 @@ } }, + // Get the constructor for a className + getConstructor: function(className) { + // Assume className is simple and can be found at top-level (window). + // Fallback to eval to handle cases like 'My.React.ComponentName'. + // Also, try to gracefully import Babel 6 style default exports + // + var constructor; + + // Try to access the class globally first + constructor = window[className]; + + // If that didn't work, try eval + if (!constructor) { + constructor = eval.call(window, className); + } + + // Lastly, if there is a default attribute try that + if (constructor && constructor.default) { + constructor = constructor.default; + } + + return constructor; + }, + // Within `searchSelector`, find nodes which should have React components // inside them, and mount them with their props. mountComponents: function(searchSelector) { @@ -75,7 +99,7 @@ for (var i = 0; i < nodes.length; ++i) { var node = nodes[i]; var className = node.getAttribute(window.ReactRailsUJS.CLASS_NAME_ATTR); - var constructor = getConstructor(className); + var constructor = this.getConstructor(className); var propsJson = node.getAttribute(window.ReactRailsUJS.PROPS_ATTR); var props = propsJson && JSON.parse(propsJson); From 426384b650628aef08ef3de1db8d47f39d8d243e Mon Sep 17 00:00:00 2001 From: dphaener Date: Tue, 10 May 2016 10:17:05 -0700 Subject: [PATCH 5/5] Remove private getConstructor function. Whoops --- lib/assets/javascripts/react_ujs_mount.js | 25 ----------------------- 1 file changed, 25 deletions(-) diff --git a/lib/assets/javascripts/react_ujs_mount.js b/lib/assets/javascripts/react_ujs_mount.js index 4a5e8c861..92813db49 100644 --- a/lib/assets/javascripts/react_ujs_mount.js +++ b/lib/assets/javascripts/react_ujs_mount.js @@ -2,31 +2,6 @@ // jQuery is optional. Use it to support legacy browsers. var $ = (typeof window.jQuery !== 'undefined') && window.jQuery; - // Get the constructor for a className - // Not a part of the public API - function getConstructor(className) { - // Assume className is simple and can be found at top-level (window). - // Fallback to eval to handle cases like 'My.React.ComponentName'. - // Also, try to gracefully import Babel 6 style default exports - // - var constructor; - - // Try to access the class globally first - constructor = window[className]; - - // If that didn't work, try eval - if (!constructor) { - constructor = eval.call(window, className); - } - - // Lastly, if there is a default attribute try that - if (constructor && constructor.default) { - constructor = constructor.default; - } - - return constructor; - } - window.ReactRailsUJS = { // This attribute holds the name of component which should be mounted // example: `data-react-class="MyApp.Items.EditForm"`