如何在next.js中使用localStorage?我尝试了3种方法,但都不起作用

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

这是我的代码,我想为切换主题编写一个上下文提供程序。 自定义主题提供者:

'use client'
import React, {createContext, useState} from "react";

type ThemeContextType = {
  theme: string;
  toggleTheme: () => void;
};

export const ThemeContext = createContext<ThemeContextType>({
  theme: 'light',
  toggleTheme: () => {}
});

export default function CustomThemeProvider({children}: Readonly<{
  children: React.ReactNode;
}>) {
  const initialTheme = window.localStorage.getItem('theme') === null ? 'light' : String(window.localStorage.getItem('theme'))
  const [theme, setTheme] = useState(initialTheme);

  const toggleTheme = () => {
    const newTheme = theme === 'dark' ? 'light' : 'dark';
    window.localStorage.setItem('theme', newTheme);
    setTheme(newTheme);
  };

  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      {children}
    </ThemeContext.Provider>
  );
}

布局内容:

'use client'
import React, {useContext} from "react";
import {ThemeContext} from "@/app/CustomThemeProvider";
import Footer from "@/app/components/Footer";
import Navigation from "@/app/components/Navigation";

export default function LayoutContent({
                         children,
                       }: Readonly<{
  children: React.ReactNode;
}>) {
  const {theme, toggleTheme} = useContext(ThemeContext);

  return (
    <html lang="en" className={theme}>
    <body>
    <div id="layout" className="layout flex-col flex min-h-screen bg-skin-base">

      <Navigation themeToggleHandler={toggleTheme}/>

      <div className="flex-1">
        {children}
      </div>

      <div>
        <Footer/>
      </div>

    </div>
    </body>
    </html>
  );
}

我写了上面的代码,我的网络风暴告诉我错误:

我尝试修改它。第一次尝试:


let initialTheme = 'light';
    if (typeof window !== "undefined") {
    initialTheme = window.localStorage.getItem('theme') === null ? 'light' : String(window.localStorage.getItem('theme'))
}
const \[theme, setTheme\] = useState(initialTheme);

它确实有效,但另一个错误显示:

第二次尝试: useEffect(),但它有切换延迟。 你能帮我吗,谢谢!

没有错误,并且切换主题流畅。

reactjs next.js
1个回答
0
投票

如果你想避免闪光,你可以只使用 CSS 来实现深色主题样式 - 我可以看到你正在使用 tailwind,它有一个方便的

dark:
修饰符。然后,您可以将脚本添加到
public
目录并直接使用
<script>
标签引用它,因为它不会与应用程序的其余部分捆绑在一起:https://tailwindcss.com/docs/dark-mode #支持系统首选项和手动选择。只要将标签放置在实际页面内容之上,就不会导致闪烁,因为它将在文档的其余部分之前首先被解析。请注意,您将不再需要提供程序,因为所有样式都将依赖于 CSS。每当您想要更新主题时,只需更改
<html>
标签上的类并更新
localStorage

或者,您可以使用服务器组件,并使用 cookie。您可以将初始值作为 prop 传递给提供者,而不是从

localStorage
获取它。 https://nextjs.org/docs/app/building-your-application/rendering/composition-patterns#using-context-providers https://nextjs.org/docs/app/api-reference/functions/饼干

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