From ec20f1bc8720e51ef7cf2f3dd55423722839e9dd Mon Sep 17 00:00:00 2001 From: ginnoir Date: Wed, 6 May 2026 16:20:49 -0500 Subject: [PATCH] Fix offline banner stuck after DevTools network toggle The online event could fire between page load and useEffect registering its listener, leaving isOffline stuck at true despite navigator.onLine being true. A zero-delay setTimeout after listener registration re-syncs from navigator.onLine, covering that race. Co-Authored-By: Claude Sonnet 4.6 --- src/components/pwa-register.tsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/components/pwa-register.tsx b/src/components/pwa-register.tsx index 39d3613..7114894 100644 --- a/src/components/pwa-register.tsx +++ b/src/components/pwa-register.tsx @@ -4,10 +4,7 @@ import { useEffect, useState } from "react"; export function PwaRegister() { const [showUpdate, setShowUpdate] = useState(false); - // Lazy init reads navigator.onLine on the client; SSR always returns false. - const [isOffline, setIsOffline] = useState( - () => typeof navigator !== "undefined" && !navigator.onLine - ); + const [isOffline, setIsOffline] = useState(false); const [mutationFailed, setMutationFailed] = useState(false); useEffect(() => { @@ -15,6 +12,10 @@ export function PwaRegister() { const handleOnline = () => setIsOffline(false); window.addEventListener("offline", handleOffline); window.addEventListener("online", handleOnline); + // Re-sync after listeners are registered in case the online/offline event + // fired between page load and this effect running (e.g. DevTools toggle). + const syncId = setTimeout(() => setIsOffline(!navigator.onLine), 0); + if (!("serviceWorker" in navigator)) { return () => { @@ -48,6 +49,7 @@ export function PwaRegister() { navigator.serviceWorker.addEventListener("message", handleMessage); return () => { + clearTimeout(syncId); window.removeEventListener("offline", handleOffline); window.removeEventListener("online", handleOnline); navigator.serviceWorker.removeEventListener(