fix(tradein/ui): чистить TanStack Query cache при смене identity (#2567) (#2651)
All checks were successful
Deploy Trade-In / changes (push) Successful in 9s
Deploy Trade-In / test (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / build-frontend (push) Successful in 2m2s
Deploy Trade-In / deploy (push) Successful in 1m9s
All checks were successful
Deploy Trade-In / changes (push) Successful in 9s
Deploy Trade-In / test (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / build-frontend (push) Successful in 2m2s
Deploy Trade-In / deploy (push) Successful in 1m9s
This commit is contained in:
parent
59c072fc4c
commit
5162659277
3 changed files with 24 additions and 5 deletions
|
|
@ -20,7 +20,6 @@ import { useRouter } from "next/navigation";
|
|||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
|
||||
import { apiFetch, HTTPError } from "@/lib/api";
|
||||
import { ME_QUERY_KEY } from "@/lib/useMe";
|
||||
import { AnonSupportWidget } from "@/components/auth/AnonSupportWidget";
|
||||
|
||||
interface LoginInput {
|
||||
|
|
@ -140,7 +139,11 @@ export default function LoginPage() {
|
|||
const loginMutation = useMutation({
|
||||
mutationFn: loginRequest,
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ME_QUERY_KEY });
|
||||
// #2567: вход под другим юзером без предварительного logout (тот же
|
||||
// девайс/вкладка) — снимаем ВЕСЬ кэш, не только /me, иначе
|
||||
// team/employees, история оценок и т.п. предыдущего юзера переживают
|
||||
// login и могут отрисоваться до первого рефетча.
|
||||
queryClient.clear();
|
||||
router.push(sanitizeNext(readNextParam()));
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
* задвоил бы префикс в `/trade-in/trade-in/history`.
|
||||
*/
|
||||
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useEffect } from "react";
|
||||
|
||||
|
|
@ -62,6 +63,7 @@ export default function GuardedRoute({
|
|||
children: React.ReactNode;
|
||||
}) {
|
||||
const router = useRouter();
|
||||
const queryClient = useQueryClient();
|
||||
// Абсолютный путь сайта: BASE_PATH + rawPath. Аккуратно с двойным слэшем
|
||||
// на `/`: `BASE_PATH = "/trade-in"` + `"/"` → `/trade-in/` (ок).
|
||||
const absolutePath = BASE_PATH
|
||||
|
|
@ -85,6 +87,13 @@ export default function GuardedRoute({
|
|||
|
||||
useEffect(() => {
|
||||
if (!shouldRedirectToLogin) return;
|
||||
// #2567: сессия протухла (401) — снимаем кэш ДО редиректа на /login. Тот
|
||||
// же самый девайс/вкладка может через секунду залогиниться другим
|
||||
// юзером; без clear() здесь team/employees, история оценок и т.п.
|
||||
// предыдущего юзера дожидались бы login-точки (её `clear()` тоже
|
||||
// сработает, но лучше не полагаться на единственную точку сброса —
|
||||
// 401 — самостоятельный путь смены identity, не только logout/login).
|
||||
queryClient.clear();
|
||||
// PR #2562 review finding 3: deep-links carry их state в query (`/v2?id=
|
||||
// <uuid>` — см. next.config.ts redirect comment про restore-by-id). Без
|
||||
// `window.location.search` юзер, чья сессия истекла mid-session на такой
|
||||
|
|
@ -93,7 +102,7 @@ export default function GuardedRoute({
|
|||
// поэтому `window` тут безопасен без typeof-guard.
|
||||
const next = `${rawPath}${window.location.search}`;
|
||||
router.push(`/login?next=${encodeURIComponent(next)}`);
|
||||
}, [shouldRedirectToLogin, rawPath, router]);
|
||||
}, [shouldRedirectToLogin, rawPath, router, queryClient]);
|
||||
|
||||
// #801: preview-страница самодостаточна (свой QueryClient с фейковым me),
|
||||
// RBAC к ней не применяем. Только под флагом — в проде по умолчанию выключено.
|
||||
|
|
|
|||
|
|
@ -14,13 +14,20 @@
|
|||
* локальный logout (кэш + редирект) выполняется в `onSettled`, а не только
|
||||
* `onSuccess`: сетевой сбой / уже-протухшая сессия не должны запирать юзера
|
||||
* на странице без возможности разлогиниться.
|
||||
*
|
||||
* #2567: `clear()`, а не точечный invalidate ME_QUERY_KEY — иначе кэш
|
||||
* остального (team/employees, история оценок, квоты) переживает logout и
|
||||
* может отрисоваться следующему юзеру той же вкладки до первого рефетча.
|
||||
* `clear()` безопасен для in-flight запросов: TanStack Query создаёт для
|
||||
* снятого из кэша ключа новый `Query`-инстанс при следующей подписке, так
|
||||
* что поздний resolve старого fetch пишет в осиротевший объект, а не в
|
||||
* видимый кэш.
|
||||
*/
|
||||
|
||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
import { apiFetch } from "@/lib/api";
|
||||
import { ME_QUERY_KEY } from "@/lib/useMe";
|
||||
|
||||
async function logoutRequest(): Promise<void> {
|
||||
await apiFetch<{ ok: boolean }>("/api/v1/auth/logout", { method: "POST" });
|
||||
|
|
@ -33,7 +40,7 @@ export function useLogout() {
|
|||
return useMutation({
|
||||
mutationFn: logoutRequest,
|
||||
onSettled: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ME_QUERY_KEY });
|
||||
queryClient.clear();
|
||||
router.push("/login");
|
||||
},
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue