From f6fe3815cbb2a5b0cc4d048d9d447a4327fbd2b7 Mon Sep 17 00:00:00 2001 From: Chris Parsons Date: Sat, 28 Feb 2026 09:19:45 -0800 Subject: [PATCH] fix: eliminate queue tab flash on mobile by using useSyncExternalStore useMediaQuery initialized to false and updated in useEffect, causing a paint where isMobile was false on mobile devices. This rendered the desktop layout first, hiding the queue tab until the effect fired. useSyncExternalStore reads matchMedia synchronously on the client so the correct layout is used on the first render with no extra paint. Co-Authored-By: Claude Sonnet 4.6 --- app/hooks/useMediaQuery.ts | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/app/hooks/useMediaQuery.ts b/app/hooks/useMediaQuery.ts index adf0f65..e184f1e 100644 --- a/app/hooks/useMediaQuery.ts +++ b/app/hooks/useMediaQuery.ts @@ -1,15 +1,13 @@ -import { useState, useEffect } from "react"; +import { useSyncExternalStore } from "react"; export function useMediaQuery(query: string): boolean { - const [matches, setMatches] = useState(false); - - useEffect(() => { - const mq = window.matchMedia(query); - setMatches(mq.matches); - const handler = (e: MediaQueryListEvent) => setMatches(e.matches); - mq.addEventListener("change", handler); - return () => mq.removeEventListener("change", handler); - }, [query]); - - return matches; + return useSyncExternalStore( + (callback) => { + const mq = window.matchMedia(query); + mq.addEventListener("change", callback); + return () => mq.removeEventListener("change", callback); + }, + () => window.matchMedia(query).matches, + () => false + ); }