NextJS 和 localstorage - 如何正确使用它?

问题描述 投票:0回答:1
"use client";
import { usePathname } from "next/navigation";
import Image from "next/image";
import i18n from "../../app/i18n";
import styles from "./styles.module.css";
import BR from "../../assets/images/official-pics/flags/BR.svg";
import FR from "../../assets/images/official-pics/flags/FR.svg";
import GE from "../../assets/images/official-pics/flags/GE.svg";
import SP from "../../assets/images/official-pics/flags/SP.svg";
import US from "../../assets/images/official-pics/flags/US.svg";
import BRAdvLogo from "../../assets/images/official-pics/bradv/logobradv.png";
import Socials from "../Socials";
import { useTranslation } from "react-i18next";
import { useLocalStorage } from "../../Hooks/useLocalStorage";

export default function Navbar() {
  const { t } = useTranslation();
  const pathname = usePathname();

  //code below to load last language used
  useLocalStorage("i18nextLng", "pt");

  const handleChangeLanguage = (value: string) => {
    i18n.changeLanguage(value);
  };

  return (
    <div className={styles.container}>
      <div className={styles.content}>
        <Image src={BRAdvLogo} alt="logo" width={64} height={64} />
        <Socials />

        <div className={styles.nav}>
          <a className={pathname === "/" ? styles.active : ""} href="/">
            {t("navbar.home")}
          </a>
          <a
            className={pathname === "/quem-somos" ? styles.active : ""}
            href="/quem-somos"
          >
            {t("navbar.about")}
          </a>
          <a
            className={pathname === "/contato" ? styles.active : ""}
            href="/contato"
          >
            {t("navbar.contact")}
          </a>
          <a className={pathname === "/blog" ? styles.active : ""} href="/blog">
            {t("navbar.blog")}
          </a>
        </div>

        <div className={styles.available__languages}>
          <div>
            <button onClick={() => handleChangeLanguage("pt")}>
              <Image src={BR} alt="Brazil" />
            </button>
            <button onClick={() => handleChangeLanguage("en")}>
              <Image src={US} alt="United States" />
            </button>
            <button onClick={() => handleChangeLanguage("fr")}>
              <Image src={FR} alt="France" />
            </button>
            <button onClick={() => handleChangeLanguage("de")}>
              <Image src={GE} alt="Germany" />
            </button>
            <button onClick={() => handleChangeLanguage("es")}>
              <Image src={SP} alt="Spain" />
            </button>
          </div>
        </div>
      </div>
    </div>
  );
}

所以我有上面的代码,用于导航栏组件,它使用 i18next 更改语言。这是一个 NextJS 项目。这适用于开发模式,但是当我尝试构建它时,它说 localStorage is not Defined(甚至使用像上面的代码这样的钩子或直接调用

localStorage.getItem('i18nextLng')
)。

我知道 localStorage 是一个浏览器变量,服务器端渲染的页面无法访问它,但这个组件是客户端渲染的,所以我不知道为什么它不起作用。

似乎找不到解决办法!

reactjs next.js build local-storage i18next
1个回答
0
投票

错误原因有:

  • Next.js 在客户端渲染(CSR)之前执行服务器端渲染(SSR)。
  • 正如您所提到的,SSR 中的 Next.js 可能无法访问全局对象,例如
    window
    document
  • window
    仅存在于客户端。因此,在定义
    localStorage
    之前,可能无法访问
    window

解决方案1:

typeof window !== 'undefined'

if (typeof window !== 'undefined') {
   const item = localStorage.getItem('key)
}

上面的代码等待客户端挂载,然后访问localStorage。如果没有引用

window
,则返回未定义。同样,我们需要在访问 localStorage 之前对其进行定义。

解决方案 2:

useEffect

useEffect(() => {
  const item = localStorage.getItem('key')
}, [])

useEffect
钩子是在客户端渲染中执行的,因此在Next.js SSR时不会执行。 => localStorage定义后我们就可以安全地访问它了。

祝你好运!

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