我有一个身份验证组件,用于检查用户是否拥有来自本地存储的令牌,这是我的代码:
import { useRouter } from "next/router";
import { useState } from "react";
const Index = (WrappedComponent: any) => {
return (props: any) => {
if (typeof window !== "undefined") {
const Router = useRouter();
const accessToken = localStorage.getItem("token");
if (!accessToken) {
Router.replace("/authentication/login");
return null;
}
return <WrappedComponent {...props} />;
}
// If we are on server, return null
return null;
};
};
export default Index;
我将它用于 /pages 目录中的组件,如下所示:
import PageContainer from "../src/components/container/PageContainer";
import FullLayout from "../src/layouts/full/FullLayout";
import ShortList from "@/src/components/dashboard/ShortList";
import withAuth from "@/src/auth";
const Index = () => {
return (
<FullLayout>
<PageContainer title="Sample Page" description="this is Sample page">
<ShortList />
</PageContainer>
</FullLayout>
);
};
export default withAuth(Index);
但是我得到这个错误: 错误:Hydration 失败,因为初始 UI 与服务器上呈现的内容不匹配。
我该如何解决这个问题?
我的下一个 js 版本是 13.
我尝试使用 useState 但没有用
在服务器上,
typeof window
将是 undefined
,但在客户端上,即使是 在初始渲染之前,window
将不再是未定义的,导致水合作用错误,因为您的服务器渲染的 HTML 与 React 不同现在有水合作用。
因为
useEffect
只在服务端运行,所以可以这样查看自己是在客户端还是服务端:
import { useRouter } from "next/router";
import { useState, useEffect } from "react";
const Index = (WrappedComponent: any) => {
return (props: any) => {
const [isMounted, setIsMounted] = useState(false);
useEffect(() => {
setIsMounted(true);
}, []);
const Router = useRouter();
if (!isMounted) {
// If we are on the server, return null
return null;
}
const accessToken = localStorage.getItem("token");
if (!accessToken) {
Router.replace("/authentication/login");
return null;
}
return <WrappedComponent {...props} />;
};
};
export default Index;
一般来说,这个检查:
if (typeof window !== "undefined")
总是会导致错误,并且没有按预期工作。
我推荐 Joshua Comeau 的这篇关于反应水合作用/补液问题的帖子https://www.joshwcomeau.com/react/the-perils-of-rehydration/#dynamic-sections-4
请记住,在此示例中,索引页面最初将完全空白,因为它现在基本上是客户端呈现的,这可能会损害 SEO。
要解决此问题,您应该将身份验证数据存储在 cookie 中,并且已经检查 next.js
middleware
用户是否登录,并可能在中间件内部而不是在客户端上重定向。