如何在 _document.js 和 Next.js 上的页面之间共享 React 上下文?

How to share React context between _document.js and pages on Next.js?

假设我有这个上下文:

export const ThemeContext = createContext();

export function ThemeWrapper({ children }) {
  const sharedState = {
    darkMode: false,
  };

  return (
    <ThemeContext.Provider value={sharedState}>
      {children}
    </ThemeContext.Provider>
  );
}

export function useThemeContext() {
  return useContext(ThemeContext);
}

我可以像这样在 _document.js 上访问:

import Document, { Html, Head, Main, NextScript } from "next/document";
import { ThemeWrapper, ThemeContext } from "../context/theme";

class MyDocument extends Document {
  static contextType = ThemeContext;
  render() {
    console.log("theme", this.context);
    return (
      <Html>
        <Head />
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

class Wrapped extends Document {
  render() {
    return (
      <ThemeWrapper>
        <MyDocument />
      </ThemeWrapper>
    );
  }
}

export default Wrapped;

现在我也想从一个页面访问这个上下文:

import { useThemeContext } from "../context/theme";

const SomePage = () => {
  const theme = useThemeContext();

  console.log("theme", theme);

  return (
    <div>Hi, I'm a page</div>
  );
};
首次加载页面时,

_document.js 在 Next.js 控制台上注销 theme { darkMode: false }SomePage 在 Chrome 上注销 theme undefined ] 控制台每次导航到它。

有什么建议吗?

我需要根据上下文在 html 标签上切换一些 class。正在尝试 manually toggle dark mode using Tailwind CSS.

ThemeWrapper 包装 _document 不会让您访问页面内的上下文(可能是因为 it's only rendered in the server),您需要为此包装 _app .请注意,_document 不会在上下文状态更改时重新呈现。

对于这个特定的用例,另一种方法是使用 next-themes.