next-themes
next-themes copied to clipboard
i cannot add Providers component at layout.tsx for webpack error
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" } }
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.
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 😊🤔
In [email protected]
, the ThemeProvider
is a client component, so you shouldn't need a wrapper anymore.