#24 Client Hints, Client Data, and Optimistic UI โ 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
๐ฅ 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
๐ฅ 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
๐บ 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
๐ 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
๐ 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
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
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