Search code examples
reactjsnext.jssupabase

How to fix Hydration with supabase auth


I started to work with NextJS, and I have this hydration error : Error: Hydration failed because the initial UI does not match what was rendered on the server.

The Component :

"use client";

import { useState, useEffect } from "react";
import { supabase } from "@/lib/supabaseClient";
import { Auth } from "@supabase/auth-ui-react";
import { ThemeSupa } from "@supabase/auth-ui-shared";
import { Session } from "@supabase/supabase-js";

export default function Login() {
  const [session, setSession] = useState<Session | null>(null);

  useEffect(() => {
    supabase.auth.getSession().then(({ data: { session } }) => {
      setSession(session);
    });

    if (typeof window !== "undefined") {
      const {
        data: { subscription },
      } = supabase.auth.onAuthStateChange((_event, session) => {
        setSession(session);
      });

      return () => subscription.unsubscribe();
    }
  }, []);

  if (!session) {
    return (
      <div className="min-h-screen flex flex-col items-center justify-center">
        <div className="w-full max-w-md">
          <Auth
            supabaseClient={supabase}
            appearance={{
              theme: ThemeSupa,
            }}
            providers={[]}
          />
        </div>
      </div>
    );
  }
}

Thanks for your helping ! :)

I want to understand why is hydration and how fix it


Solution

  • You might probable have to wait until the component mounts. This simple old trick could fix it.

    "use client";
    
    import { useState, useEffect } from "react";
    import { supabase } from "@/lib/supabaseClient";
    import { Auth } from "@supabase/auth-ui-react";
    import { ThemeSupa } from "@supabase/auth-ui-shared";
    import { Session } from "@supabase/supabase-js";
    
    export default function Login() {
      const [session, setSession] = useState<Session | null>(null);
      const [isMounted, setIsMounted] = useState(false);
    
      useEffect(() => {
        setIsMounted(true);
    
        supabase.auth.getSession().then(({ data: { session } }) => {
          setSession(session);
        });
    
        if (typeof window !== "undefined") {
          const {
            data: { subscription },
          } = supabase.auth.onAuthStateChange((_event, session) => {
            setSession(session);
          });
    
          return () => subscription.unsubscribe();
        }
      }, []);
    
      if (!isMounted) {
        return null;
      }
    
      if (!session) {
        return (
          <div className="min-h-screen flex flex-col items-center justify-center">
            <div className="w-full max-w-md">
              <Auth
                supabaseClient={supabase}
                appearance={{
                  theme: ThemeSupa,
                }}
                providers={[]}
              />
            </div>
          </div>
        );
      }
    }