teilai teilai
teilai teilai

Reputation: 51

how to add theme provider in next.js app?

i want to add themeprovider to my app so i can easily change between dark and light mode

this how my layout.tsx looks like:

import "./globals.css";
import "@/styles/nav.css";
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import { ApolloProvider } from "@apollo/client";
import createApolloClient from "./apollo";
import Header from "./header";
import { ThemeProvider } from "styled-components";
import { darkTheme } from "@/styles/ThemeConfig";

const inter = Inter({ subsets: ["latin"] });
const client = createApolloClient();

export const metadata: Metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body className={inter.className}>
        <ThemeProvider theme={darkTheme}>
          <Header></Header>
          {children}
        </ThemeProvider>
      </body>
    </html>
  );
}

i'm getting error: Server Error Error: createContext only works in Client Components. Add the "use client" directive at the top of the file to use it. Read more: https://nextjs.org/docs/messages/context-in-server-component

if i'm adding use client to layout.tsx my page still dont work and i'm getting other error Failed to compile ./src\app\layout.tsx ReactServerComponentsError:

You are attempting to export "metadata" from a component marked with "use client", which is disallowed. Either remove the export, or the "use client" directive. Read more: https://nextjs.org/docs/getting-started/react-essentials#the-use-client-directive

how to add theme provider?

import { createGlobalStyle } from "styled-components";

export const lightTheme = {
  body: "#FFF",
  text: "#363537",
  toggleBorder: "#FFF",
  background: "#363537",
};

export const darkTheme = {
  body: "#363537",
  text: "#FAFAFA",
  toggleBorder: "#6B8096",
  background: "#999",
};

export const GlobalStyles = createGlobalStyle`
  body {
    background: ${({ theme }) => theme.body};
    color: ${({ theme }) => theme.text};
    font-family: Tahoma, Helvetica, Arial, Roboto, sans-serif;
    transition: all 0.50s linear;
  }
`;

Upvotes: 5

Views: 10445

Answers (1)

Robin Thomas
Robin Thomas

Reputation: 4146

You are getting the error:

Server Error Error: createContext only works in Client Components. Add the "use client" directive at the top of the file to use it. Read more:

https://nextjs.org/docs/messages/context-in-server-component

because ThemeProvider is supposed to be run on client-side (meaning a client-component). All client components in Next.js need to be marked with "use client" directive.

Since your ThemeProvider component is from styled-components, that means you cannot mark it as "use client".


The next option is to make RootLayout as a client component. But,

The root layout is a Server Component by default and can not be set to a Client Component.

https://nextjs.org/docs/app/building-your-application/routing/pages-and-layouts#layouts

So you cannot add "use client" to src/app/layout.tsx as well.


That means the only option is to create another component (which will be a client component) and you need to use ThemeProvider inside it. Then use this component in RootLayout.

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body className={inter.className}>
        <ThemeClient>
          <Header></Header>
          {children}
        </ThemeClient>
      </body>
    </html>
  );
}
"use client"

import { darkTheme } from "@/styles/ThemeConfig";

export default function ThemeClient({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <ThemeProvider theme={darkTheme}>
      {children}
    </ThemeProvider>
  )
} 

Upvotes: 10

Related Questions