Skip to content
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

Event turbo:before-render is fired twice, unless caching is disabled. #1183

Open
andriytyurnikov opened this issue Feb 10, 2024 · 7 comments

Comments

@andriytyurnikov
Copy link

While I was trying to implement animated transitions, I've noticed that
turbo:before-render is fired twice sometimes (quite often, but not at first).

Furter investigation revealed that adding
<meta name="turbo-cache-control" content="no-cache">
fixes the issue.
However it disables a cache.

I humbly request to consider having separate events for cached content and to ensure rendering lifecycle events to be fired once.

@mdesantis
Copy link

mdesantis commented Feb 10, 2024

With Turbo 8.0.0.beta.2 it was possible to check event.detail.isPreview to handle no-cache and cache renderings, I wonder if now there is another way

@andriytyurnikov
Copy link
Author

@mdesantis thanks a lot for your input.
This property is not there anymore, but data-turbo-preview attribute is still there.

@mdesantis
Copy link

I see, so this is the workaround nowadays:

addEventListener("turbo:before-render", (event) => {
  event.detail.render = (currentElement, newElement) => {
    if (document.documentElement.hasAttribute("data-turbo-preview"))
      console.log('cache')
    else
      console.log('no cache')
  }
})

I wish Turbo exposed a stable API for this, so we don't have to cross the fingers every library update :D

@andriytyurnikov
Copy link
Author

@mdesantis - yep, seems to work for now.
But in this particular case (animated transitions) supporting caching adds substantial challenges of it's own, and ignoring it is practically impossible

@jdelStrother
Copy link

Looks like the isPreview property got reverted here: bb735bf , although the docs still reference it here: https://turbo.hotwired.dev/reference/events#turbo%3Abefore-render

The alternative seems pretty unwieldy - you need to override event.detail.render? So really you'd need something like this:

document.addEventListener("turbo:before-render", function (e) {
  let ogRender = e.detail.render;
  e.detail.render = (...args: any[]) => {
    if (document.documentElement.hasAttribute("data-turbo-preview")) {
      console.log("preview");
    } else {
      console.log("no preview");
    }
    return ogRender(...args);
  };
});

@Ambient-Impact
Copy link

You don't need to override event.detail.render() at all; this should work at the start of a turbo:before-render handler:

// Don't do anything if this is a cached preview being shown.
if (event.target.hasAttribute('data-turbo-preview') === true) {
  return;
}

@jdelStrother
Copy link

Ohhh. Yep, that works - thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

4 participants