Reputation: 2003
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
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
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
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