Disabling JavaScript

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 and your data loading, links, and even forms will still work.

Here’s how we like to do it:

Open up each route module you want to include JavaScript for and add a “handle”. This is way for you to provide any kind of meta information about a route to the parent route (as you’ll see in a moment).

  1. export const handle = { hydrate: true };

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

  1. import React from "react";
  2. import {
  3. Meta,
  4. Links,
  5. Scripts,
  6. Outlet,
  7. useMatches
  8. } from "remix";
  9. export default function App() {
  10. const matches = useMatches();
  11. // If at least one route wants to hydrate, this will return true
  12. const includeScripts = matches.some(
  13. match => match.handle?.hydrate
  14. );
  15. // then use the flag to render scripts or not
  16. return (
  17. <html lang="en">
  18. <head>
  19. <meta charSet="utf-8" />
  20. <Meta />
  21. <Links />
  22. </head>
  23. <body>
  24. <Outlet />
  25. {/* include the scripts, or not! */}
  26. {includeScripts && <Scripts />}
  27. </body>
  28. </html>
  29. );
  30. }

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 client-side transitions.

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

  1. <select id="qty">
  2. <option>1</option>
  3. <option>2</option>
  4. <option value="contact">Contact Sales for more</option>
  5. </select>
  6. <script
  7. dangerouslySetInnerHTML={{
  8. __html: `
  9. document.addEventListener('DOMContentLoaded', () => {
  10. document.getElementById('qty').onchange = (event) => {
  11. if (event.target.value === "contact") {
  12. window.location.assign("/contact")
  13. }
  14. }
  15. });
  16. `,
  17. }}
  18. />