Skip to content

Webpacker + Turbolinks + ReactRailsUJS = 😞 #899

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
mendelk opened this issue Jun 5, 2018 · 4 comments · Fixed by #900
Closed

Webpacker + Turbolinks + ReactRailsUJS = 😞 #899

mendelk opened this issue Jun 5, 2018 · 4 comments · Fixed by #900

Comments

@mendelk
Copy link
Contributor

mendelk commented Jun 5, 2018

Steps to reproduce

Create a new Rails app that uses Webpacker for assets, and imports Turbolinks (as opposed to using Sprockets for Turbolinks as seems to be the case for this repo's tests).

Run ReactRailsUJS.detectEvents() to set up Turbolinks' events.

Expected behavior

ReactRailsUJS should mount and unmount React components on the corresponding Turbolinks events.

Actual behavior

Those events don't get fired.

System configuration

Webpacker: 3.2.0
React-Rails version: 2.4.4
React_UJS version: 2.4.4

The reason this happens is because React-Rails expects Turbolinks to be a global object. If you're using Webpacker, by default everything is local, causing React-Rails to think that Turbolinks is not installed.

(My attempt to solve this via using a webpack.ProvidePlugin to turn Turbolinks into a global did not work, because Turbolinks.start() needs to be called before React-Rails, else Turbolinks.controller is undefined.)

I'm not sure this can be considered a bug, so instead I'll just share how I solved this. If this is intended, perhaps it can be added to README / Uncyclo? (I can create a PR if desired!)

My solution:

import Turbolinks from "turbolinks";
import ReactRailsUJS from "react_ujs";

// This needs to be in this particular order:
Turbolinks.start();
// Add Turbolinks to the global namespace
window.Turbolinks = Turbolinks;
// Remove previous (native) events, and add Turbolinks'
ReactRailsUJS.detectEvents();
// (Optional) Clean up global namespace
delete window.Turbolinks;

Cheers!

@ttanimichi
Copy link
Member

👀

@BookOfGreg
Copy link
Member

BookOfGreg commented Jun 6, 2018

Was last tested in #868 where I fixed a double mount.
Do you have a reproduction?

Edit: I understand what you mean now, yes when I tested that Turbolinks was loaded via sprockets.
If you're willing to offer a PR we'd gladly review it.

@mendelk
Copy link
Contributor Author

mendelk commented Jun 6, 2018

@BookOfGreg Should I try coming up with a solution to avoid relying on Turbolinks being global, or should I expand the README to clarify this possibility? The former is probably more "correct", but will require greater changes.

@BookOfGreg
Copy link
Member

In general this gem should avoid making changes or having specific integrations with other gems/packages.
Turbolinks does fall into the exceptions for this along with JQuery because they are/were Rails defaults and so common.

How are you supposed to deal with overloading .ready() in Turbolinks5? For sprockets we have the Turbolinks detector but that doesn't work in Webpack world, though surely Turbolinks doesn't break everyone else listening for .ready()

I'd rather not make Turbolinks global to make the detector keep working, if possible lets document what the fix is and then look into something to replace the detector in both Sprockets and Webpack worlds.

mendelk added a commit to mendelk/react-rails that referenced this issue Jun 6, 2018
soundasleep added a commit to soundasleep/rpg that referenced this issue Sep 27, 2019
Use setup instructions from
reactjs/react-rails#899 to get Turbolinks +
webpacker + react-rails to work correctly
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants