hotwired / turbo

The speed of a single-page web application without having to write any JavaScript
https://turbo.hotwired.dev
MIT License
6.69k stars 423 forks source link

using data-turbo-action "replace" or "advance" cause turbo:before-cache event to be called on live page #1259

Open dbil25 opened 4 months ago

dbil25 commented 4 months ago

The Docs (https://turbo.hotwired.dev/handbook/building#preparing-the-page-to-be-cached) suggest we listen to the before-cache event to tear down controllers and prepare for a page cache. But having a turbo frame loaded with data-turbo-action="advance" or "replace" somehow dispatches a before-render event on the newly loaded live page, which in my case breaks a couple of controllers.

I'm pretty sure this event has no reason to be dispatched on a live page, it should only be dispatched when exiting a page.

I'll try to reverse-engineer the turbo source code and if I find the culprit i'll open a PR, but so far no luck.

This wrongfully called page cache is the root cause of some other issues as well: https://github.com/hotwired/turbo/issues/1075 https://github.com/hotwired/turbo/issues/919 https://github.com/hotwired/turbo/issues/1008

YummYume commented 3 months ago

I second this, the documentation encourages us to prepare pages to be cached, and this often means disposing of third party libraries and such, and then reinstating them. We frequently use data-action for that purpose, such as turbo:before-cache@window->my-controller#dispose, which works very well... Until there's a turbo-frame on the page.

The easiest "way" to fix it for now is to disable cache on the page, which is definitely not optimal, as we also use cache for smoother navigation and restoration of various state (a slide the user was at, or a timestamp on a video...).

I really think the dispatching of this event is a mistake, because it's dispatched after every other event, even after turbo:frame-load, so we can't even use this event to set up the controllers again.

HolyMacarony commented 2 months ago

This problem is still relevant. I spent several hours today, trying to find a way to make it work but just ended up giving up and disabling the cache entirely too. My Problem is that you cannot use select2 with turbo frames, because the select2 fields duplicate when you use browser navigation... It looks like that: https://stackoverflow.com/questions/36497723/select2-with-ajax-gets-initialized-several-times-with-rails-turbolinks-events

diniscorreia commented 2 months ago

I’m running into the same issue. I was already using the before-cache event (adding the listener on connect) to teardown some third-party widgets, but recently hit the problem when using it with a Turbo Frame.

Disabling the cache on the page was not an option. I came up with a messy workaround (emphasis on messy): I added a state variable in my teardown method, setting it to false on turbo:frame-render and true on turbo:click. This way, the teardown runs when going to a different page but doesn’t run when navigating within the frame (since turbo:frame-render fires after turbo:click).

elsanits commented 1 day ago

This problem also affects turbo:before-visit event