next-themes icon indicating copy to clipboard operation
next-themes copied to clipboard

i cannot add Providers component at layout.tsx for webpack error

Open saramjh opened this issue 1 year ago • 1 comments

i was following tutorial of Nextjs 13 of this youtube and then error was occured at that part of 12:10.

error message is following below `Unhandled Runtime Error TypeError: webpack_require.n is not a function. (In 'webpack_require.n(react__WEBPACK_IMPORTED_MODULE_0__)', 'webpack_require.n' is undefined) Call Stack eval

[native code] (app-pages-browser)/./node_modules/next-themes/dist/index.module.js

file:///Users/urs/DEV/blog-next-13/.next/static/chunks/app/layout.js (18:5)

/_next/static/chunks/webpack.js (704:35) webpack_require

file:///Users/urs/DEV/blog-next-13/.next/static/chunks/webpack.js (37:37) eval

[native code] (app-pages-browser)/./app/components/Providers.tsx

/_next/static/chunks/app/layout.js (50:5)

file:///Users/urs/DEV/blog-next-13/.next/static/chunks/webpack.js (704:35) webpack_require

/_next/static/chunks/webpack.js (37:37)`

isn't next-themes right version for nextjs13 or something?

{ "name": "blog-next-13", "version": "0.1.0", "private": true, "scripts": { "dev": "next dev", "build": "next build", "start": "next start", "lint": "next lint" }, "dependencies": { "@types/node": "20.4.2", "@types/react": "18.2.15", "@types/react-dom": "18.2.7", "autoprefixer": "10.4.14", "eslint": "8.45.0", "eslint-config-next": "13.4.10", "next": "^13.4.11", "next-themes": "^0.2.1", "postcss": "8.4.26", "react": "18.2.0", "react-dom": "18.2.0", "tailwindcss": "3.3.3", "typescript": "5.1.6" }, "devDependencies": { "@tailwindcss/typography": "^0.5.9" } }

saramjh avatar Jul 21 '23 07:07 saramjh

it looks like you are using app-dir. Currently next-themes don't come out of the box with 'use client'. so Rather than importing <ThemeProvider> directly from "next-themes", create a new Theme provider file with 'use client' and import that one instead. This is given in the next-themes/examples/app-dir example. ThemeProvider.js

"use client";
import * as React from "react";
import { ThemeProvider as NextThemesProvider } from "next-themes";

/**
 * Your app's theme provider component.
 * 'use client' is essential for next-themes to work with app-dir.
 */
export function ThemeProvider({ children, ...props }) {
  return <NextThemesProvider {...props}>{children}</NextThemesProvider>;
}

and in the layout.js

....
import { ThemeProvider } from "./components/ThemeProvider";
....

This fixed my issue. Ideally 'next-themes' can export a file with 'use client' directive and it will be much easier.

sandrinjoy avatar Oct 31 '23 10:10 sandrinjoy

I guess by now, everything with Next.js 14 latest version (event with less compatible versions) with next-themes working fine. I implemented the below code using the Next.js 14 version and haven't faced any errors so far.

Create a new Theme provider file with 'use client' and then create ThemeToggle.tsx file:

Theme Provider Filer

'use client'

import * as React from 'react'
import { ThemeProvider as NextThemesProvider } from 'next-themes'
type ThemeProviderProps = Parameters<typeof NextThemesProvider>[0]

export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
  return <NextThemesProvider {...props}>{children}</NextThemesProvider>
}

Theme Toggle File

'use client'

import { useTheme } from 'next-themes'

function ThemeToggle() {
  const { theme, setTheme } = useTheme()

  return (
    <button
      className="mt-16 px-4 py-2 text-white dark:text-black bg-black dark:bg-white font-semibold rounded-md"
      onClick={() => {
        setTheme(theme === 'light' ? 'dark' : 'light')
      }}
    >
      Change Theme
    </button>
  )
}

export default ThemeToggle

**Now In Layout.tsx file - don't need to use any suppress warning **

import type { Metadata } from 'next'
import { Inter } from 'next/font/google'
import './globals.css'
import { ThemeProvider } from './components/ThemeProvider'

const inter = Inter({ subsets: ['latin'] })

export const metadata: Metadata = {
  title: 'Viral Siddhapura',
  description: 'Generated by Viral Siddhapura',
}

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body className='bg-white dark:bg-black min-h-[100dvh]'>
        <ThemeProvider attribute="class">{children}</ThemeProvider>
      </body>
    </html>
  )
}

This fixed my issue. My portfolio is also live based on this code. Hope this help you 😊🤔

viral-siddhapura avatar Mar 13 '24 18:03 viral-siddhapura

In [email protected], the ThemeProvider is a client component, so you shouldn't need a wrapper anymore.

pacocoursey avatar Mar 13 '24 23:03 pacocoursey