Suggest an editImprove this articleRefine the answer for “How does Context work in Server Components?”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**A Provider can be declared on the server** - you can create a context and set `value` in a Server Component, and every nested **Client** component will be able to read it via `useContext`. **Key point:** the context value must be serializable, and state changed in a client Provider cannot "raise" changes back to the server, because server components have already been rendered for the request.Shown above the full answer for quick recall.Answer (EN)Image## How this works 1. **A Provider can be declared on the server** You can create a context and set `value` in a Server Component - every nested **Client** component will be able to read it via `useContext`. 2. **The context value must be serializable** Everything that goes from the server to the client must be safely serialized. => Use primitives and simple objects/arrays. Not allowed: functions, class instances, proxies, DOM nodes, etc. Allowed: strings, numbers, booleans, `null`, plain objects, arrays (and anything you're ready to turn into JSON yourself). 3. **Context flows top-down, not back up** Context set on the server is available to the client. But state changed in a client Provider **cannot "raise" changes back to the server**: server components have already been rendered for the request. 4. **A client-only Provider cannot be imported from the server** If a Provider uses `useState/useEffect` hooks and is marked `"use client"`, you cannot import it directly from a Server Component. Wrap the tree through a client "wrapper" component. 5. **Per-request isolation** Server Components render on every request. Context created on the server (for example, from cookies/headers/DB) is automatically **scoped to a specific request** (great for locale, auth, feature flags). --- ## Mini-example (Next.js / RSC) **shared/context.ts** ```javascript import { createContext } from "react"; export type AppCtx = { locale: string; userName?: string | null }; export const AppContext = createContext<AppCtx>({ locale: "en" }); ``` **app/layout.tsx** (Server Component) ```javascript import { cookies } from "next/headers"; import { AppContext } from "@/shared/context"; export default async function RootLayout({ children }: { children: React.ReactNode }) { const cookieStore = await cookies(); const locale = cookieStore.get("locale")?.value ?? "en"; // the value must be serializable: const value = { locale, userName: null }; return ( <html lang={locale}> <body> <AppContext.Provider value={value}> {children} </AppContext.Provider> </body> </html> ); } ``` **components/UserGreeting.tsx** (`"use client"`) ```javascript "use client"; import { useContext } from "react"; import { AppContext } from "@/shared/context"; export function UserGreeting() { const { locale, userName } = useContext(AppContext); return <p>{userName ? `Hi, ${userName}!` : `Locale: ${locale}`}</p>; } ``` Here the `Provider` on the server hands out `value`, and the client component reads it via `useContext`. --- ## Practical tips - **Split contexts** by area (locale/auth/theme) to avoid unnecessary re-renders of client consumers. - **Don't put secrets in context**: anything available to the client is considered "public". Keep access logic on the server, and pass only "safe" derived values into the context. - **Memoize large values on the client side** (if the Provider is a client one) to avoid triggering unnecessary re-renders (`useMemo` for `value`). - **For client-side dynamics** (theme, toggles) wrap the relevant part of the tree with a client Provider. This won't affect the server components above it.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.