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

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