I'm using Supabase with NextJS to make a dashboard and I'm facing this kind of trouble:
Every time a user get into the application, the Login page flash for 1 second and then authenticate the user and redirect to a content page.
Video showing the problem: https://user-images.githubusercontent.com/48700146/214397435-a0bb3623-2097-4fdf-80c8-982a1d77a0a2.mp4
As you can see, I'm not using Supabase login component.
Layout.tsx
interface Props {
children: React.ReactNode;
}
export default function Layout({ children }: Props) {
const supabaseSession = useSession();
return (
<>
<Head>
<title>LysiMed</title>
</Head>
{supabaseSession ? (
<Flex className={inter.className}>
<Menu />
<Box flex={1}>{children}</Box>
</Flex>
) : (
<Login />
)}
</>
);
}
_app.tsx
export default function App({
Component,
pageProps,
}: AppProps<{ initialSession: Session }>) {
const [loading, setLoading] = React.useState(false);
const [supabase] = useState(() => createBrowserSupabaseClient());
React.useEffect(() => {
const start = () => {
setLoading(true);
};
const end = () => {
setLoading(false);
};
Router.events.on("routeChangeStart", start);
Router.events.on("routeChangeComplete", end);
Router.events.on("routeChangeError", end);
return () => {
Router.events.off("routeChangeStart", start);
Router.events.off("routeChangeComplete", end);
Router.events.off("routeChangeError", end);
};
}, []);
return (
<SessionContextProvider
supabaseClient={supabase}
initialSession={pageProps.initialSession}
>
<ChakraProvider>
{loading ? (
<Loading>
<Spinner size="xl" color="green.400" />
</Loading>
) : (
<Layout>
<Component {...pageProps} />
</Layout>
)}
</ChakraProvider>
</SessionContextProvider>
);
}
package.json
{
"next": "13.0.7",
"@supabase/auth-helpers-nextjs": "^0.5.2",
"@supabase/auth-helpers-react": "^0.3.1",
"@supabase/supabase-js": "^2.2.3",
}
I think that this kind of problem is happening because useSession() is asynchronous and it returns null while Supabase client checks user credentials.
Whats the best way to solve this?
useSession()most likely returns aisLoadingor similar property, and you can use it to optionally render a loading component:isLoading ? <Loading /> : <Layout />