When we try to use a ThemeProvider(as shown below) in NextJS, we need to declare this Provider as a client component. But in NextJS docs it is said that if we declare a component as a client component all other modules imported into it, including child components, are considered part of the client bundle – and will be rendered by React on the client.
Since our whole application component live inside the provider, does it mean all of the child component would behave as client comps. If that’s the case, doesn’t it completely eliminate SSR using NextJS? I’m curious about this interaction and how it aligns with the SSR and CSR principles that Next.js is built upon.
//layout.tsx
import { Provider } from './provider'
import '@/styles//globals.css'
import type { Metadata } from 'next'
import { Inter } from 'next/font/google'
const inter = Inter({ subsets: ['latin'] })
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}>
<Provider attribute="class" defaultTheme="dark">
{children}
</Provider>
</body>
</html>
)
}
//provider.tsx
'use client'
import { ThemeProvider as NextThemesProvider } from "next-themes"
import { type ThemeProviderProps } from "next-themes/dist/types"
import { NextUIProvider } from "@nextui-org/react"
export function Provider({ children, ...props }: ThemeProviderProps) {
return (
<NextUIProvider>
<NextThemesProvider {...props}>
{children}
</NextThemesProvider>
</NextUIProvider>
)
}
I am asking this question as a newbie in NextJS, so please excuse any technical inaccuracies or lack of experience in my query.
2
Answers
In the updated doc itself it has been clarified later on in the composition pattern
In summary:
Your assumption that we need to use client component for creating a context is correct.
So to create a Provider, we need to make it a client component like:
But you can import this client component inside a server component without any issue, like:
Without the
use client
, this component is treated as a server component.On a side note, server components are new. So if you are trying to import a provider from a third party library, chances are, they are not using
"use client"
yet.If that’s the case, if you try to import that provider into your server component, that shall throw error:
Error: "createContext" can't be used in Server Components
.To solve this, you need to wrap the third-party provider inside a client component, before using it in a server component.
This
MyAppProvider
will be rendered only on the client (meaning, only in client bundle), even thought it hasThirdPartyProvider
(which is a server component).If you import a server component into a client component, that server component will be rendered as a client component.