Fix stale closure bug in QueryProvider (token ref) and add warning toast so users know why they were redirected to login.
66 lines
2.1 KiB
TypeScript
66 lines
2.1 KiB
TypeScript
"use client";
|
|
|
|
import {
|
|
QueryCache,
|
|
QueryClient,
|
|
QueryClientProvider,
|
|
MutationCache,
|
|
} from "@tanstack/react-query";
|
|
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
|
import { useState, useRef, useEffect } from "react";
|
|
import { useRouter } from "next/navigation";
|
|
import { toast } from "sonner";
|
|
import { AuthProvider, useAuthContext } from "@/context/auth-context";
|
|
import { Toaster } from "@/components/ui/sonner";
|
|
import { ApiRequestError } from "@/lib/api";
|
|
|
|
function QueryProvider({ children }: { children: React.ReactNode }) {
|
|
const { token, setToken } = useAuthContext();
|
|
const router = useRouter();
|
|
const tokenRef = useRef(token);
|
|
useEffect(() => { tokenRef.current = token; }, [token]);
|
|
|
|
const [queryClient] = useState(() => {
|
|
return new QueryClient({
|
|
queryCache: new QueryCache({
|
|
onError: (error) => {
|
|
// Only redirect on 401 if the user had a token (expired session).
|
|
// Guests hitting 401 on restricted content should not be redirected.
|
|
if (error instanceof ApiRequestError && error.status === 401 && tokenRef.current) {
|
|
toast.warning("Session expired, please log in again.");
|
|
setToken(null);
|
|
router.push("/login");
|
|
}
|
|
},
|
|
}),
|
|
mutationCache: new MutationCache({
|
|
onError: (error) => {
|
|
// Mutations always require auth — redirect on 401 regardless.
|
|
if (error instanceof ApiRequestError && error.status === 401) {
|
|
toast.warning("Session expired, please log in again.");
|
|
setToken(null);
|
|
router.push("/login");
|
|
}
|
|
},
|
|
}),
|
|
defaultOptions: { queries: { staleTime: 60 * 1000 } },
|
|
});
|
|
});
|
|
|
|
return (
|
|
<QueryClientProvider client={queryClient}>
|
|
{children}
|
|
<Toaster position="bottom-right" richColors />
|
|
<ReactQueryDevtools initialIsOpen={false} />
|
|
</QueryClientProvider>
|
|
);
|
|
}
|
|
|
|
export function Providers({ children }: { children: React.ReactNode }) {
|
|
return (
|
|
<AuthProvider>
|
|
<QueryProvider>{children}</QueryProvider>
|
|
</AuthProvider>
|
|
);
|
|
}
|