如何修复认证组件中的水化错误

问题描述 投票:0回答:1

我有一个身份验证组件,用于检查用户是否拥有来自本地存储的令牌,这是我的代码:

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 但没有用

reactjs authentication next.js next
1个回答
0
投票

在服务器上,

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
用户是否登录,并可能在中间件内部而不是在客户端上重定向。

© www.soinside.com 2019 - 2024. All rights reserved.