Integrate LiveView and Turbolinks lifecycles

I’m trying to implement multiple LiveViews in our Phoenix app which uses Turbolinks.
When switching pages Turbolinks replaces the page content, but LiveViews is not aware of this and are not disconnected/destroyed.

I noticed the LiveViews are piling up by logging liveSocket.roots. In the example below you see there are 2 LiveViews initially (which is correct). When navigating from there you see new instances being added where the old instances are not being removed:

This results in JavaScript errors when the LiveView is removed from the DOM but is still receiving updates:

How we initialize and connect:

import { Socket } from "phoenix";
import LiveSocket from "phoenix_live_view";

const liveSocket = new LiveSocket("/live", Socket, {
  params: { _csrf_token: window.csrfToken }
});

// Fires once after the initial page load, and again after every Turbolinks visit
document.addEventListener("turbolinks:load", () => {
  liveSocket.connect();
});

What would be the recommended way to integrate LiveViews with Turbolinks?
Is there a way to have both lifecycles to play nice together?

1 Like