v0.21.0
Branches
main (2.15.0)dev
Versions
2.15.01.19.3v0.21.0
Viewing docs for an older release. View latest

Do you ever look at a page on your site and think "why are we loading all of this JavaScript? There's nothing on this page but links!" This may seem a little odd for a JavaScript framework, but you can easily turn off JavaScript with a boolean but your data loading and links will still all work.

Here's how we like to do it:

Add a handle to JavaScript Enabled Route Modules

Open up each route module you want to include JavaScript for and add this:

export let handle = { hydrate: true };

Now open root.tsx, bring in useMatches and add this:

import React from "react";
import {
  Meta,
  Links,
  Scripts,
  Outlet,
  useMatches
} from "remix";

export default function App() {
  let matches = useMatches();

  // If at least one route wants to hydrate, this will return true
  let includeScripts = matches.some(
    match => match.handle?.hydrate
  );

  // then use the flag to render scripts or not
  return (
    <html lang="en">
      <head>
        <meta charSet="utf-8" />
        <Meta />
        <Links />
      </head>
      <body>
        <Outlet />
        {/* include the scripts, or not! */}
        {includeScripts && <Scripts />}
      </body>
    </html>
  );
}

All of your data loading will still work on the server render, and all of your <Link>s render normal <a> underneath, so they will continue to work.

On any page, at anytime, you can flip between plain HTML and full clientside transitions.

I need tiny bit of JavaScript though.

If you need one tiny bit of interactivity, use a <script dangerouslySetInnerHTML>.

<select id="qty">
  <option>1</option>
  <option>2</option>
  <option value="contact">Contact Sales for more</option>
</select>
<script
  dangerouslySetInnerHTML={{
    __html: `
      document.addEventListener('DOMContentLoaded', () => {
        document.getElementById('qty').onchange = (event) => {
          if (event.target.value === "contact") {
            window.location.assign("/contact")
          }
        }
      });
    `,
  }}
/>

There's little reason to load 100kb of JavaScript for one small interactive piece of a landing page.

Docs and examples licensed under MIT