9

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.

user3174311
  • 1,714
  • 5
  • 28
  • 66

3 Answers3

5

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.

SteveB
  • 155
  • 1
  • 9
  • 1
    `window.location` is accessed inside the anchor's `onClick` callback, which is executed on user action on the client-side. It never gets to run on the server. And even if it did, the error would be different. – juliomalves May 10 '22 at 18:17
0

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.

Igor Gonak
  • 2,050
  • 2
  • 10
  • 17
0

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} />;
}

Alex Rintt
  • 1,618
  • 1
  • 11
  • 18