user3174311
user3174311

Reputation: 2003

Error: Hydration failed because the initial UI does not match what was rendered on the server with useSession() and react-bootstrap

I am using next.js, react18 and next-auth. I have a login component that checks the session and displays a login or logout link, depending on you are logged in or not

import Link from 'next/link';

const Login = () => {
    const {data: session} = useSession();

    if (session) {
        return <Link href="#"><a onClick={() => signOut({callbackUrl: `${window.location.origin}`})}>Sign out</a></Link>
    } else {
        return <Link href="#"><a onClick={() => signIn()}>Log in</a></Link>
        
    }

this used to work as expected, but then I installed react-bootstrap, I changed the links like this

import {Nav} from "react-bootstrap";

return <Nav.Link href="#"><a onClick={() => signOut({callbackUrl: `${window.location.origin}`})}>Sign out</a></Nav.Link>;
return <Nav.Link href="#"><a onClick={() => signIn()}>Log in</a></Nav.Link>;

and I started to get this error

Error: Hydration failed because the initial UI does not match what was rendered on the server.

I know I could downgrade to react 17 or just use the 'next/link' component but I am looking for a workaround before to give up.

Upvotes: 9

Views: 20026

Answers (3)

Alex
Alex

Reputation: 2434

Just adding my 2 cents here, I was using Gatsby and this error was coming up because I was rendering nothing on the server-side but in the client-side I was returning an element, like this:


export default function MyCustomCanvasAnimation() {
  const isSSR = typeof window === "undefined";

  const canvasRef = useRef<HTMLCanvasElement>(null);

  useEffect(() => {
    if (isSSR) return;

    const canvas = canvasRef.current;

    if (!canvas) return;

    let animationFrameId: number

    function render() {
      animationFrameId = window.requestAnimationFrame(() => { .... })
    }

    render();

    return () => {
      window.cancelAnimationFrame(animationFrameId);
    };
  }, [canvasRef, mousePosition]);

  // This line was causing the error
  if (isSSR) return <></>;

  return <canvas ref={canvasRef} />;
}

Upvotes: 0

SteveB
SteveB

Reputation: 153

It's because you're referencing the window, which doesn't exist on the Server. The error was there in 17 as well, but React 18 is stricter, and will error out.

Upvotes: 5

Igor Gonak
Igor Gonak

Reputation: 2260

I don't know much about next.js, but react-bootstrap's Nav.Link component already renders an anker element, so you have link in a link. Try to use following:

<Nav.Link href="#" onClick={() => signOut({callbackUrl: `${window.location.origin}`})}>Sign out</a></Nav.Link>;

I see you rather doing some action then navigating. Maybe you can try to use Button with variant="link" or just use something else instead of anchor element.

Why do you use Nav.Link and react-bootstrap at all? Nav.Link only add styles, nothing else, no magic.

Upvotes: 0

Related Questions