Search code examples
reactjsruby-on-railsesbuild

Rails 7 + esbuild + React flicker when changing pages


I have a new Rails project using esbuild with React. The setup is pretty standard:

<div
  id="user_edit_page"
  data-controller="user-edit-page"
>
</div>

And then a:

import { Controller } from "@hotwired/stimulus"
import React from "react";
import { createRoot } from "react-dom/client";
import UserEditPage from "../components/UserEditPage";

// Connects to data-controller="user-edit-page"
export default class extends Controller {
  connect() {
    const app = document.getElementById("user_edit_page");
    createRoot(app).render(<UserEditPage />)
  }
}

When I navigate between pages there is a really annoying flicker. It feels that Rails is serving a cached response, then re-initializes the React component, which then re-renders.

I'm assuming I can disable turbolinks and have this go away, but I was wondering if there's a nice Rails way to have things working as intended.


Solution

  • You could disable the caching on the turbolinks in the <head> of the layout. <meta name="turbolinks-cache-control" content="no-cache">. That is one option, or I think you could create a loading screen mechanism to wait for the page to be loaded before rendering.

    What version of React are you using? Are you using React-Router (if so, what version)? Could you create an async function in a useEffect hook to wait for the component to load before rendering? That would prevent the flickering.

    It seems like Ruby turbolinks and React Routing do not get along with each other because the ruby link link will do a full page refresh in Rails by default.

    Edit: Depending on version, you might need to change turbolinks-cache-control to turbo-cache-control