From 81cd1f61d38435bbde63c044fe53f0d3f4517937 Mon Sep 17 00:00:00 2001 From: bot-frontend Date: Sun, 31 May 2026 16:07:21 +0300 Subject: [PATCH] =?UTF-8?q?fix(tradein):=20RouteGuard=20prod=20401=20?= =?UTF-8?q?=E2=86=92=20session-expired=20screen,=20stop=20re-subscribe=20s?= =?UTF-8?q?torm=20(#800)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TanStack Query errored queries (staleTime: Infinity) are always stale — each new observer subscription triggers a refetch regardless of retry:false. RouteGuard mounting children on 401 caused continuous re-subscribe churn (616+ requests in 15s confirmed by design-loop repro 2026-05-31). Fix: on 401 in production, render NoAccessScreen variant="session" instead of mounting the app subtree. Dev without Caddy keeps the passthrough (process.env.NODE_ENV !== "production") so local next dev still works. Also adds NoAccessScreen "session" variant (title: Сессия истекла, subtitle: Обновите страницу, чтобы войти снова). --- .../frontend/src/components/auth/NoAccessScreen.tsx | 12 +++++++----- .../frontend/src/components/auth/RouteGuard.tsx | 7 ++++++- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/tradein-mvp/frontend/src/components/auth/NoAccessScreen.tsx b/tradein-mvp/frontend/src/components/auth/NoAccessScreen.tsx index 3afffb4f..06ef425d 100644 --- a/tradein-mvp/frontend/src/components/auth/NoAccessScreen.tsx +++ b/tradein-mvp/frontend/src/components/auth/NoAccessScreen.tsx @@ -10,15 +10,17 @@ */ interface NoAccessScreenProps { - variant: "user" | "path"; + variant: "user" | "path" | "session"; path?: string; } export function NoAccessScreen({ variant, path }: NoAccessScreenProps) { const subtitle = - variant === "user" - ? "Учётная запись не привязана к роли. Обратитесь к администратору GenDesign — kopylov." - : "У вашей роли нет доступа к этому разделу. Вернитесь на главную или обратитесь к администратору."; + variant === "session" + ? "Сессия истекла или вы не авторизованы. Обновите страницу, чтобы войти снова." + : variant === "user" + ? "Учётная запись не привязана к роли. Обратитесь к администратору GenDesign — kopylov." + : "У вашей роли нет доступа к этому разделу. Вернитесь на главную или обратитесь к администратору."; return (
- Доступа нет + {variant === "session" ? "Сессия истекла" : "Доступа нет"}

{children}; + // Dev without Caddy: 401 is normal, mount the app so local dev works. + // Prod: mounting children on 401 causes TanStack Query re-subscribe storm + // (each new observer on errored query triggers a refetch). Show session screen + // instead — prevents the subtree from mounting, kills the loop. + if (process.env.NODE_ENV !== "production") return <>{children}; + return ; } if (error instanceof HTTPError && error.status === 403) {