Jacob Paris
โ† Back to all content

#24 Client Hints, Client Data, and Optimistic UI โ€“ Remix Community Newsletter

Hey folks, Jacob Paris here with another issue of Moulton, the Remix Community Newsletter!

Let's get to it!

Featured ๐Ÿ”ฅ Epic Web Client Hints

Back in March, I published an article on server-side rendering dates across timezones with Remix.

Since then it was integrated into the Epic Stack and has evolved into a whole client hints solution

Client Hints are a way of hinting user preferences to the server so the user doesn't get a flash of incorrect content

  • dark/light mode
  • screen size
  • timezone and locale
  • reduced motion settings

Now Kent has extracted it into its own package that's much more flexible and can be easily integrated into your app

https://github.com/epicweb-dev/client-hints

๐Ÿ”ฅ Client Data API hits pre-release

Remix's new Client Data API is available in pre-release with npx upgrade-remix 2.4.0-pre.2

With this you have fine grained control over whether your fetches and mutations happen on the server or the client and can even mix and match

  • new clientLoader and clientAction exports
  • you can choose whether to run the clientLoader on hydration or to render a loading state
  • client loaders are not blocked by deferred data in server loaders, so you could return a (non-deferred) API key from the server

github.com/remix-run/remix/discussions/7634

๐Ÿ’ก What's next in Remix?

In the latest Remix Roadmap session, Michael and Ryan went over the upcoming middleware and server context features in Remix

Currently, the browser makes many small requests for each nested route loader on navigations, which posed a big problem for middleware support since middleware would run on each of those requests

  • the Single Fetch proposal combines all those requests into a single request to the server
  • Middleware can then run in parallel before those requests are processed
  • Server Context functions run before the middleware and are available to all middleware and loaders

Depending on whether you want server code to run in parallel or serially, you'll be able to move logic between server context, middleware, and the loader functions.

The exact way of defining server context vs middleware and which routes they operate on is still being worked out

youtu.be/fHel4d-It5Q

๐Ÿ”ฅ useDebounceFetcher joins Remix Utils

One of my more popular articles shows how to create a custom fetcher hook that implements a debounce strategy for submission.

This is useful for any sort of autosaving functionality where you might want to submit a form after a user has stopped typing for second, or immediately when they leave the field.

This hook has now been included into Remix Utils as useDebounceFetcher and generally deprecates the old article.

jacobparis.com/content/use-debounce-fetcher

๐Ÿ“„ Keep your loader data fresh in Remix with long-polling

Sergio Xalambrรญ wrote a tutorial on how to keep your loader data fresh in Remix with long-polling.

  • revalidate on an interval with useRevalidator
  • handle slow/offline network connections with useSyncExternalStore
  • avoid revalidation when the browser is set to Save Data mode

sergiodxa.com/tutorials/keep-your-loader-data-fresh-in-remix

๐Ÿ“บ Optimistic UI in Remix with useSubmit

Sam Selikoff teaches how to implement optimistic UI in Remix with useSubmit while handling race conditions and de-duplication.

  • use the useSubmit hook with navigate: false to create a new fetcher instance for each submission
  • create a client UUID to use as the fetcher key so that the fetcher is reused when the user submits the same form multiple times
  • read the fetcher status to show items optimistically while submitting
  • use the client ID to de-duplicate optimistic items

youtu.be/d0p95C3Kcsg

๐Ÿ”ฅ Submit a form without overriding query params

When you submit a GET form, the browser will replace all the query params with the names and values from the form.

If you want to keep some existing query params, this ExistingSearchParams component will create a hidden input for each one

  • explicitly exclude fields you want to overwrite
  • put forms in components that can be reused without breaking other forms on the page

This component has been included in Remix Utils as ExistingSearchParams

jacobparis.com/content/existing-params

๐Ÿ“บ Realtime data with server-sent events

At Remix London, Moishi Netzer shows a demo of using server-sent events to subscribe to a realtime feed of new todos in a Remix app.

  • remix-utils has eventStream and useEventSource helpers to make this easy
  • create a resource route that returns an eventStream and sends each new change
  • subscribe to the stream with useEventSource to show the data in a React component

twitter.com/remix_london/status/1722671667879543113

๐Ÿ“„ Redirect routes

Redirect routes are resource routes that just send the user to another page, like /items/4/next that will look through the database for the next matching ID and redirect there

jacobparis.com/content/remix-redirect-routes

๐Ÿ“บ Remix Dev Tools is a Vite plugin now

The Remix Dev Tools have been extracted into a Vite plugin to make integration much easier

Now it's just plugins: [remixDevTools(), remix()]

twitter.com/AlemTuzlak59192/status/1730590526355693725

Alem also sat down with Brooks to go over Remix Dev Tools and show off some functionality

youtu.be/VZH9cmeSwnc

๐Ÿ“บ Exploring progressive enhancement in Remix

If you're new to the concept of progressive enhancement, this video by Daniel Kanem is a great introduction and covers what it means for Remix.

twitter.com/DanielKanem/status/1730241888307892706

๐Ÿ”ฅ Epic Web releases Scroll Restoration

Remix has a built in ScrollRestoration component that restores the scroll position when navigating back to a page.

But if you have your own scrollable containers, Epic Web has released a package that recreates this functionality for any scrollable element.

github.com/epicweb-dev/restore-scroll

๐Ÿ”ฅ Strip server-code from your production sourcemaps

Remix recommends against including sourcemaps in production because they can leak server code to the client.

But if you want them anyway, to make debugging easier, this package from Michael Kiliman will strip out the loaders, actions, and other server code from client side sourcemaps.

github.com/kiliman/strip-sourcemaps

๐Ÿ“„ Expose Remix Routes as API Endpoints

You can use resource routes to expose your loaders and actions as API endpoints.

If they're completely identical, you can just import the loader or action and re-export it from the other route

But if they differ, like session based auth on the web app and JWT auth on the API, it's best to extract the shared logic into a regular function

sergiodxa.com/tutorials/expose-remix-routes-as-api-endpoints

๐Ÿ”ฅ Remix Mailer with previews

Greger Mendle has released a small package that makes it easy to create email preview routes inside your Remix app, as well as intercepting emails during dev

github.com/gregermendle/remix-mailer

๐Ÿ“บ Remix Learning videos

Nikos has a playlist of videos on Youtube that teach different Remix concepts and features

youtu.be/PLualcIC6WNK3Nm-mMrS17ES0B4FDUsIrJ

๐Ÿ“บ Remixing Toast Notifications

Alem Tuzlak sits with Brooks from the Remix team to talk about how to use flash session data for toast notifications in Remix

youtu.be/N2yMZR6B31U

๐Ÿ“„ Real time file upload progress indicators

Andre Koenig shows how to make file uploads with real time progress indicators in Remix

andrekoenig.de/articles/progressively-enhanced-file-uploads-remix

๐Ÿ“บ Remix philosophy talk

At Conf42 2023, Ken Snyder gave a talk on the philosophy behind Remix

  • the simplicity of building apps
  • the server/client model
  • embracing web standards
  • and the future roadmap for the Remix framework

youtu.be/A-GwPQJ2wyQ

๐Ÿ“„ Upload images to a third party storage provider

When uploading images, you might want to bypass your own server and have the client upload them directly to a cloud storage provider like S3 or Cloudflare Images

  • Users select images to upload from a file input
  • They're uploaded in the background to the cloud from the client
  • Then we add hidden inputs with their uploaded URL

jacobparis.com/content/remix-image-uploads

๐Ÿ”ฅ Open source util site built in Remix

Hussein Jafferjee has built an open-source Remix site with a bunch of useful utilities for developers, such as JSON formatting, base64 encoding, and more

utiliti.dev

There's more community meetups than ever

There are active Remix meetups all around the world. If you're interested in meeting other Remix users, learning more about the framework, or just hanging out with some cool folks, check out one of these meetups.

  • ๐Ÿ‡บ๐Ÿ‡ธ Lehi, Utah
  • ๐Ÿ‡ฎ๐Ÿ‡ณ Pune, India
  • ๐Ÿ‡ฌ๐Ÿ‡ง London, UK
  • ๐Ÿ‡บ๐Ÿ‡ธ New York City
  • ๐Ÿ‡ง๐Ÿ‡ท Sรคo Paulo, Brasil
  • ๐Ÿ‡บ๐Ÿ‡ธ Austin, Texas
  • ๐Ÿ‡บ๐Ÿ‡ธ San Francisco, California
  • ๐Ÿ‡ฎ๐Ÿ‡ฑ Tel Aviv, Israel
  • ๐Ÿ‡ฒ๐Ÿ‡ฝ Mexico City, Mexico
  • ๐Ÿ‡ฉ๐Ÿ‡ฐ Copenhagen, Denmark
  • ๐Ÿ‡ฟ๐Ÿ‡ฆ Johannesburg, South Africa
  • ๐Ÿ‡ธ๐Ÿ‡ช Uppsala, Sweden
  • ๐Ÿ‡จ๐Ÿ‡ท San Jose, Costa Rica

meetup.com/pro/remix-run

This is not a one-way conversation

On behalf of the whole Remix community, Iโ€™m really glad to have you here, and I want to hear from you.

If you find something cool you'd like featured, or have questions you'd like answered, that's what I'm here for. Just hit reply and let me know, or join the conversation directly in the Remix Discord

Thanks for reading!

โ€” Jacob Paris

Professional headshot
Moulton
Moulton

Hey there! I'm a developer, designer, and digital nomad building cool things with Remix, and I'm also writing Moulton, the Remix Community Newsletter

About once per month, I send an email with:

  • New guides and tutorials
  • Upcoming talks, meetups, and events
  • Cool new libraries and packages
  • What's new in the latest versions of Remix

Stay up to date with everything in the Remix community by entering your email below.

Unsubscribe at any time.