You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Compatibility with Turbo (next version of Turbolinks) #1103
The next version of Turbolinks, now called Turbo (available for Rails via turbo-rails), is in beta and react-rails should be updated to be compatible. The new interface is similar to the old one, the events are just called differently.
The relevant events are now called turbo:load and turbo:before-render instead of turbolinks:load and turbolinks:before-render. A new event script along the following lines should do the trick:
// in react_ujs/src/events/turbo.jsmodule.exports={setup: function(ujs){ujs.handleEvent('turbo:load',ujs.handleMount);ujs.handleEvent('turbo:before-render',ujs.handleUnmount);},teardown: function(ujs){ujs.removeEvent('turbo:load',ujs.handleMount);ujs.removeEvent('turbo:before-render',ujs.handleUnmount);},}
Along with this some changes to the detection script will be required, but I'm not familiar enough to be able to tell exactly what needs to be added.
Hotfix
I have solved this issue in my app by adding the following two lines to the application.js script:
// earlier: var ujs = require("react_ujs");ujs.handleEvent('turbo:load',ujs.handleMount);ujs.handleEvent('turbo:before-render',ujs.handleUnmount);
For anyone already using Turbo and looking to also use react-rails, the above is a hotfix until it's implemented in the package.
Thanks to the contributors for taking a look at this.
Another thing to consider is turbo-frame events once that is merged hotwired/turbo#59
At the moment React components that come in via a frame do not mount even with the above hotfix. And as per the above PR there is currently no existing events to tap into.
Another thing to consider is turbo-frame events once that is merged hotwired/turbo#59
At the moment React components that come in via a frame do not mount even with the above hotfix. And as per the above PR there is currently no existing events to tap into.
Has anyone gotten this to work recently? I have the latest version (v7.0.1) installed locally and am still unable to render react-rails components in a turbo frame...
Personally, I’ve started using Stimulus components whenever possible, since they work seamlessly even within turbo frames. It’s a compromise, since Stimulus doesn’t allow for easy DOM manipulation, but I’ve been able to make due so far.
@dvruette thanks the for the response! Stimulus is the goal for me too. Unfortunately we have a lot of random react components that we can't immediately migrate so I was hoping to shim them into turbo frames until we have time to do that.
I got the components we were rendering inside of stuff that I moved to a turbo frame to work by doing three things:
I had to declare the props in the controller (hashes sent as props to react_component didn't seem to be rendering as expected within a turbo frame and I got parsing errors; just passing @props solved the parsing issue)
I needed to change some of the links inside of react-rendered components to have target='_top' so that they don't get commandeered by turbo
I added a listener to the frame-load event in my application.js:
document.addEventListener('turbo:frame-load', function (_e) {
ReactRailsUJS.mountComponents();
}, false);
I'm not sure if this is the cleanest way to do this but haven't found anything else so far...
@hbriggs Nice, thanks for letting me know! Good to know that there is a way now, sometimes I'd prefer to use (or reuse) React components, especially when there are lots of DOM manipulations and Stimulus isn't really a good option.
Would also be great to get this working out of the box, might take a stab at it if I find the time.
After installing react-rails and turbo-rails, I encountered the following problem.
Versions and configuration
react-rails: 2.7.0
turbo-rails: 1.4.0
app/javascript/packs/application.js: add the following snippet.
var ReactRailsUJS = require("react_ujs");
ReactRailsUJS.handleEvent('turbo:load', ReactRailsUJS.handleMount)
ReactRailsUJS.handleEvent('turbo:before-render', ReactRailsUJS.handleUnmount)
Problem. 1
After implementing useMediaQuery responsive support, the following exception occurs when changing the screen size.
Uncaught runtime errors:
ERROR
Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.
at removeChildFromContainer (http://localhost:3000/packs/js/vendors-node_modules_hotwired_turbo-rails_app_javascript_turbo_index_js-node_modules_mui_mate-95ab8d.js:66940:15)
at commitDeletionEffectsOnFiber (http://localhost:3000/packs/js/vendors-node_modules_hotwired_turbo-rails_app_javascript_turbo_index_js-node_modules_mui_mate-95ab8d.js:79856:15)
at recursivelyTraverseDeletionEffects (http://localhost:3000/packs/js/vendors-node_modules_hotwired_turbo-rails_app_javascript_turbo_index_js-node_modules_mui_mate-95ab8d.js:79819:5)
at commitDeletionEffectsOnFiber (http://localhost:3000/packs/js/vendors-node_modules_hotwired_turbo-rails_app_javascript_turbo_index_js-node_modules_mui_mate-95ab8d.js:79948:9)
at commitDeletionEffects (http://localhost:3000/packs/js/vendors-node_modules_hotwired_turbo-rails_app_javascript_turbo_index_js-node_modules_mui_mate-95ab8d.js:79806:5)
at recursivelyTraverseMutationEffects (http://localhost:3000/packs/js/vendors-node_modules_hotwired_turbo-rails_app_javascript_turbo_index_js-node_modules_mui_mate-95ab8d.js:80089:9)
at commitMutationEffectsOnFiber (http://localhost:3000/packs/js/vendors-node_modules_hotwired_turbo-rails_app_javascript_turbo_index_js-node_modules_mui_mate-95ab8d.js:80123:9)
at recursivelyTraverseMutationEffects (http://localhost:3000/packs/js/vendors-node_modules_hotwired_turbo-rails_app_javascript_turbo_index_js-node_modules_mui_mate-95ab8d.js:80103:7)
at commitMutationEffectsOnFiber (http://localhost:3000/packs/js/vendors-node_modules_hotwired_turbo-rails_app_javascript_turbo_index_js-node_modules_mui_mate-95ab8d.js:80123:9)
at recursivelyTraverseMutationEffects (http://localhost:3000/packs/js/vendors-node_modules_hotwired_turbo-rails_app_javascript_turbo_index_js-node_modules_mui_mate-95ab8d.js:80103:7)
Problem. 2
The following error occurs with each page transition.
react-dom.development.js:86 Warning: You are calling ReactDOM.unmountComponentAtNode() on a container that was previously passed to ReactDOMClient.createRoot(). This is not supported. Did you mean to call root.unmount()?
Hotfix for problem 1
The first problem can be avoided by changing the previous snippet as follows:
// Do not call 'handlerMount()' right after the page is first loaded,
// but when the page is subsequently rewritten by turbo-rails.
var skipFirstCall = false
ReactRailsUJS.handleEvent('turbo:load', ()=> {
skipFirstCall && ReactRailsUJS.handleMount()
skipFirstCall = true
})
Hotfix for problem 2
The second problem can be avoided by removing the following code:
I don't think this essentially solves the problem, but it solves the glitch anyway.
I really hope that you will be able to properly resolve the compatibility issue with turbo-rails.
Reacted by Mostafa Ahangarha, Exit Only and Luis Nazarit
I got it to work by calling unmountComponents directly, e.g.:
constcomponentRequireContext=require.context('components',true)constReactRailsUJS=require('react_ujs')ReactRailsUJS.useContext(componentRequireContext)// Prevent double mount on page loadReactRailsUJS._firstTurboLoadSkipped=falseReactRailsUJS.handleEvent('turbo:load',()=>{if(ReactRailsUJS._firstTurboLoadSkipped)ReactRailsUJS.handleMount()ReactRailsUJS._firstTurboLoadSkipped=true})// Unmount components and call cleanup functions after Turbo navigationsReactRailsUJS.handleEvent('turbo:before-render',(e)=>{ReactRailsUJS.unmountComponents(e.target)})
Reacted by Masa Morita, Aaron Breckenridge, Christiaan, Josef Strzibny, Diego Couto and Raymund Lew
This causes components to render but components are mounted/rendered multiple times. For example using useEffect hook with empty array dependency is called thrice for me.
Activity
phoozle commentedon Mar 3, 2021
Another thing to consider is turbo-frame events once that is merged
hotwired/turbo#59
At the moment React components that come in via a frame do not mount even with the above hotfix. And as per the above PR there is currently no existing events to tap into.
100terres commentedon Sep 14, 2021
@phoozle They've added
turbo:frame-renderevent hotwired/turbo#327 🙂hbriggs commentedon Oct 12, 2021
Has anyone gotten this to work recently? I have the latest version (v7.0.1) installed locally and am still unable to render
react-railscomponents in a turbo frame...dvruette commentedon Oct 12, 2021
@hbriggs Unfortunately no.
Personally, I’ve started using Stimulus components whenever possible, since they work seamlessly even within turbo frames. It’s a compromise, since Stimulus doesn’t allow for easy DOM manipulation, but I’ve been able to make due so far.
hbriggs commentedon Oct 12, 2021
@dvruette thanks the for the response! Stimulus is the goal for me too. Unfortunately we have a lot of random react components that we can't immediately migrate so I was hoping to shim them into turbo frames until we have time to do that.
I got the components we were rendering inside of stuff that I moved to a turbo frame to work by doing three things:
propsin the controller (hashes sent as props toreact_componentdidn't seem to be rendering as expected within a turbo frame and I got parsing errors; just passing@propssolved the parsing issue)target='_top'so that they don't get commandeered by turboframe-loadevent in myapplication.js:I'm not sure if this is the cleanest way to do this but haven't found anything else so far...
dvruette commentedon Oct 12, 2021
@hbriggs Nice, thanks for letting me know! Good to know that there is a way now, sometimes I'd prefer to use (or reuse) React components, especially when there are lots of DOM manipulations and Stimulus isn't really a good option.
Would also be great to get this working out of the box, might take a stab at it if I find the time.
lcampanari commentedon Aug 11, 2022
Got it to work for turbo-frame events:
MasahiroMorita commentedon Jul 29, 2023
After installing react-rails and turbo-rails, I encountered the following problem.
Versions and configuration
react-rails: 2.7.0turbo-rails: 1.4.0app/javascript/packs/application.js: add the following snippet.Problem. 1
After implementing useMediaQuery responsive support, the following exception occurs when changing the screen size.
Problem. 2
The following error occurs with each page transition.
Hotfix for problem 1
The first problem can be avoided by changing the previous snippet as follows:
Hotfix for problem 2
The second problem can be avoided by removing the following code:
I don't think this essentially solves the problem, but it solves the glitch anyway.
I really hope that you will be able to properly resolve the compatibility issue with turbo-rails.
mattboldt commentedon Oct 15, 2023
In case anyone runs into this on v3+, since components are no longer automatically unmounted here:
react-rails/react_ujs/index.js
Lines 191 to 196 in 0930f24
I got it to work by calling
unmountComponentsdirectly, e.g.:inventionsbyhamid commentedon Sep 20, 2024
I added below lines after going through comments
This causes components to render but components are mounted/rendered multiple times. For example using useEffect hook with empty array dependency is called thrice for me.
Is anyone working to add turbo support directly?