Stop refetching /me on every page mount, warm shared accounting queries, prefetch nav routes, and keep the shell visible during soft SPA transitions. Co-authored-by: Cursor <cursoragent@cursor.com>
42 lines
1.2 KiB
TypeScript
42 lines
1.2 KiB
TypeScript
"use client";
|
|
|
|
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
|
import { useCallback } from "react";
|
|
import { api, type MeResponse } from "@/lib/api";
|
|
import { getStoredToken } from "@/lib/auth";
|
|
|
|
export const ME_QUERY_KEY = ["me"] as const;
|
|
|
|
/** Shared user/tenant session — cached so sidebar navigations do not refetch /me. */
|
|
export function useMe() {
|
|
const qc = useQueryClient();
|
|
const hasToken = typeof window !== "undefined" ? !!getStoredToken() : false;
|
|
|
|
const q = useQuery({
|
|
queryKey: ME_QUERY_KEY,
|
|
queryFn: () => api.me.get(),
|
|
enabled: hasToken,
|
|
staleTime: 5 * 60_000,
|
|
gcTime: 30 * 60_000,
|
|
refetchOnMount: false,
|
|
refetchOnWindowFocus: false,
|
|
retry: 1,
|
|
});
|
|
|
|
const reload = useCallback(async () => {
|
|
if (!getStoredToken()) {
|
|
qc.setQueryData<MeResponse | null>(ME_QUERY_KEY, null);
|
|
return;
|
|
}
|
|
await q.refetch();
|
|
}, [qc, q]);
|
|
|
|
return {
|
|
me: q.data ?? null,
|
|
/** True only on the first network load (cached navigations stay instant). */
|
|
loading: hasToken ? q.isLoading : false,
|
|
error: q.error instanceof Error ? q.error.message : q.error ? String(q.error) : "",
|
|
reload,
|
|
};
|
|
}
|