简体   繁体   中英

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

Let's say I have this context:

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);
}

Which I can access on _document.js like this:

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;

Now I also want to access this context from a page:

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

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

  console.log("theme", theme);

  return (
    <div>Hi, I'm a page</div>
  );
};

_document.js logs out theme { darkMode: false } on the Next.js console when the page is first loaded but SomePage logs out theme undefined on the Chrome console everytime you navigate to it.

Any suggestions?

I need to toggle some class on the html tag depending on this context. Trying to manually toggle dark mode using Tailwind CSS .

Wrapping _document with ThemeWrapper doesn't give you access to the context inside pages (probably because it's only rendered in the server ), you will need to wrap _app for that. Just note that _document will not re-render on context state changes.

For this specific use case, an alternative is to use next-themes .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM