Skip to content

Commit 55519e2

Browse files
fix: Fix the session state
1 parent 30c210b commit 55519e2

File tree

2 files changed

+42
-30
lines changed

2 files changed

+42
-30
lines changed

src/components/providers.tsx

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,21 @@ import { ThemeProvider as NextThemesProvider } from "next-themes"
55
import { HeroUIProvider } from "@heroui/react"
66
import type { SessionValidationResult } from "@/types"
77
import { useSessionStore } from "@/state/session"
8-
import { Suspense, useEffect, useRef, RefObject } from "react"
8+
import { Suspense, useEffect, useRef, RefObject, useCallback } from "react"
99
import { useConfigStore } from "@/state/config"
1010
import type { getConfig } from "@/flags"
1111
import { EmailVerificationDialog } from "./email-verification-dialog"
1212
import { useTopLoader } from 'nextjs-toploader'
1313
import { usePathname, useRouter, useSearchParams, useParams } from "next/navigation"
14-
import { useEventListener } from 'usehooks-ts';
15-
import { useDebounceCallback } from 'usehooks-ts'
14+
import { useEventListener, useDebounceCallback } from 'usehooks-ts';
1615

1716
function RouterChecker() {
1817
const { start, done } = useTopLoader()
1918
const pathname = usePathname();
2019
const searchParams = useSearchParams();
2120
const router = useRouter();
2221
const params = useParams();
23-
const refetchSession = useSessionStore((store) => store.refetchSession)
22+
const fetchSession = useSessionStore((store) => store.fetchSession)
2423

2524
useEffect(() => {
2625
const _push = router.push.bind(router);
@@ -35,15 +34,15 @@ function RouterChecker() {
3534
// Monkey patch: https://github.com/vercel/next.js/discussions/42016#discussioncomment-9027313
3635
router.refresh = () => {
3736
start();
38-
refetchSession();
37+
fetchSession?.();
3938
_refresh();
4039
};
4140
// eslint-disable-next-line react-hooks/exhaustive-deps
4241
}, [])
4342

4443
useEffect(() => {
4544
done();
46-
refetchSession();
45+
fetchSession?.();
4746
// eslint-disable-next-line react-hooks/exhaustive-deps
4847
}, [pathname, searchParams, params]);
4948

@@ -56,13 +55,14 @@ export function ThemeProvider({
5655
}: React.ComponentProps<typeof NextThemesProvider>) {
5756
const setSession = useSessionStore((store) => store.setSession)
5857
const setConfig = useConfigStore((store) => store.setConfig)
59-
const isLoading = useSessionStore((store) => store.isLoading)
60-
const clearSession = useSessionStore((store) => store.clearSession)
6158
const refetchSession = useSessionStore((store) => store.refetchSession)
59+
const clearSession = useSessionStore((store) => store.clearSession)
6260
const documentRef = useRef(typeof window === 'undefined' ? null : document)
6361
const windowRef = useRef(typeof window === 'undefined' ? null : window)
64-
const fetchSession = useDebounceCallback(async () => {
62+
63+
const doFetchSession = useCallback(async () => {
6564
try {
65+
refetchSession() // Set loading state before fetch
6666
const response = await fetch('/api/get-session')
6767
const sessionWithConfig = await response.json() as {
6868
session: SessionValidationResult
@@ -80,26 +80,32 @@ export function ThemeProvider({
8080
console.error('Failed to fetch session:', error)
8181
clearSession()
8282
}
83-
}, 30)
83+
}, [setSession, setConfig, clearSession, refetchSession])
84+
85+
const fetchSession = useDebounceCallback(doFetchSession, 30)
8486

87+
// Initial fetch on mount
8588
useEffect(() => {
86-
if (isLoading) {
87-
fetchSession()
88-
}
89-
// eslint-disable-next-line react-hooks/exhaustive-deps
90-
}, [isLoading])
89+
fetchSession()
90+
}, [fetchSession])
9191

92+
// Handle refetches
9293
useEventListener('visibilitychange', () => {
9394
if (document.visibilityState === 'visible') {
94-
refetchSession()
95+
fetchSession()
9596
}
9697
}, documentRef as RefObject<Document>)
9798

9899
useEventListener('focus', () => {
99-
refetchSession()
100+
fetchSession()
100101
// @ts-expect-error window is not defined in the server
101102
}, windowRef)
102103

104+
// Add fetchSession to the session store
105+
useEffect(() => {
106+
useSessionStore.setState({ fetchSession: doFetchSession })
107+
}, [doFetchSession])
108+
103109
return (
104110
<HeroUIProvider>
105111
<Suspense>

src/state/session.ts

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,31 @@ import { SessionValidationResult } from '@/types';
22
import { create } from 'zustand'
33
import { combine } from 'zustand/middleware'
44

5+
interface SessionState {
6+
session: SessionValidationResult | null;
7+
isLoading: boolean;
8+
lastFetched: Date | null;
9+
fetchSession?: () => Promise<void>;
10+
}
11+
12+
interface SessionActions {
13+
setSession: (session: SessionValidationResult) => void;
14+
clearSession: () => void;
15+
refetchSession: () => void;
16+
}
17+
518
export const useSessionStore = create(
619
combine(
720
{
821
session: null as SessionValidationResult | null,
922
isLoading: true,
1023
lastFetched: null as Date | null,
11-
isInitialized: false,
12-
},
24+
fetchSession: undefined,
25+
} as SessionState,
1326
(set) => ({
14-
setSession: (session: SessionValidationResult) =>
15-
set({ session, isLoading: false, lastFetched: new Date(), isInitialized: true }),
16-
clearSession: () =>
17-
set({ session: null, isLoading: false, lastFetched: null, isInitialized: true }),
18-
refetchSession: () =>
19-
set((state) => ({
20-
...state,
21-
isLoading: !state.isInitialized,
22-
lastFetched: null
23-
})),
24-
})
27+
setSession: (session: SessionValidationResult) => set({ session, isLoading: false, lastFetched: new Date() }),
28+
clearSession: () => set({ session: null, isLoading: false, lastFetched: null }),
29+
refetchSession: () => set({ isLoading: true })
30+
} as SessionActions)
2531
)
2632
)

0 commit comments

Comments
 (0)