fix: show toast and redirect on expired session (401)
Fix stale closure bug in QueryProvider (token ref) and add warning toast so users know why they were redirected to login.
This commit is contained in:
@@ -7,8 +7,9 @@ import {
|
|||||||
MutationCache,
|
MutationCache,
|
||||||
} from "@tanstack/react-query";
|
} from "@tanstack/react-query";
|
||||||
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
||||||
import { useState } from "react";
|
import { useState, useRef, useEffect } from "react";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
|
import { toast } from "sonner";
|
||||||
import { AuthProvider, useAuthContext } from "@/context/auth-context";
|
import { AuthProvider, useAuthContext } from "@/context/auth-context";
|
||||||
import { Toaster } from "@/components/ui/sonner";
|
import { Toaster } from "@/components/ui/sonner";
|
||||||
import { ApiRequestError } from "@/lib/api";
|
import { ApiRequestError } from "@/lib/api";
|
||||||
@@ -16,6 +17,8 @@ import { ApiRequestError } from "@/lib/api";
|
|||||||
function QueryProvider({ children }: { children: React.ReactNode }) {
|
function QueryProvider({ children }: { children: React.ReactNode }) {
|
||||||
const { token, setToken } = useAuthContext();
|
const { token, setToken } = useAuthContext();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const tokenRef = useRef(token);
|
||||||
|
useEffect(() => { tokenRef.current = token; }, [token]);
|
||||||
|
|
||||||
const [queryClient] = useState(() => {
|
const [queryClient] = useState(() => {
|
||||||
return new QueryClient({
|
return new QueryClient({
|
||||||
@@ -23,7 +26,8 @@ function QueryProvider({ children }: { children: React.ReactNode }) {
|
|||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
// Only redirect on 401 if the user had a token (expired session).
|
// Only redirect on 401 if the user had a token (expired session).
|
||||||
// Guests hitting 401 on restricted content should not be redirected.
|
// Guests hitting 401 on restricted content should not be redirected.
|
||||||
if (error instanceof ApiRequestError && error.status === 401 && token) {
|
if (error instanceof ApiRequestError && error.status === 401 && tokenRef.current) {
|
||||||
|
toast.warning("Session expired, please log in again.");
|
||||||
setToken(null);
|
setToken(null);
|
||||||
router.push("/login");
|
router.push("/login");
|
||||||
}
|
}
|
||||||
@@ -33,6 +37,7 @@ function QueryProvider({ children }: { children: React.ReactNode }) {
|
|||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
// Mutations always require auth — redirect on 401 regardless.
|
// Mutations always require auth — redirect on 401 regardless.
|
||||||
if (error instanceof ApiRequestError && error.status === 401) {
|
if (error instanceof ApiRequestError && error.status === 401) {
|
||||||
|
toast.warning("Session expired, please log in again.");
|
||||||
setToken(null);
|
setToken(null);
|
||||||
router.push("/login");
|
router.push("/login");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user