错误:使用useSession()和react-bootstrap时,由于初始UI与在服务器上呈现的内容不匹配,导致水合作用失败。

9

我正在使用 next.js、react18 和 next-auth。我有一个登录组件,它检查会话并根据您是否已登录显示登录或注销链接。

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

这个本来是按照预期工作的,但是后来我安装了react-bootstrap,然后将链接更改为以下内容:

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

我开始遇到了这个错误

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

我知道我可以降级到React 17或仅使用'next/link'组件,但在放弃之前,我正在寻找一种解决方法。


你是否总是收到这个错误信息?即使你没有使用任何一个react-bootstrap组件? - Igor Gonak
不,只有当我包含上面的内容时才会。 - user3174311
下面的回答有帮助吗? - Igor Gonak
@IgorGonak 不好意思,我尝试了但没有成功。无论如何还是谢谢。 - user3174311
请问您能否分享使用react-bootstrap时组件的完整代码? - juliomalves
同样遇到这个问题,我真的不知道我做错了什么。 - naomi
3个回答

5

这是因为你引用了在服务器端不存在的 window。这个错误在 React 17 中也存在,但React 18更加严格,会报错。


1
window.location 在锚点的 onClick 回调函数中被访问,该函数在客户端上的用户操作时执行。它永远不会在服务器上运行。即使它运行了,错误也会不同。 - juliomalves

0

关于 next.js 我不是很了解,但 react-bootstrap 的 Nav.Link 组件已经渲染了一个锚点元素,所以你会在链接中再次嵌套链接。尝试使用以下代码:

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

我看到你更喜欢执行某些操作而不是导航。也许你可以尝试使用Buttonvariant="link",或者使用其他东西代替锚元素。

你为什么要使用Nav.Link和react-bootstrap呢?Nav.Link只会添加样式,没有任何魔法。


0

在这里补充一下我的看法,我正在使用 Gatsby,这个错误是因为我在服务器端没有渲染任何内容,但在客户端我返回了一个元素,就像这样:


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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接