Shared state across layouts lets different pages or sections of your app use the same data or settings. This helps keep things consistent and saves you from repeating code.
Shared state across layouts in NextJS
'use client'; import { createContext, useContext, useState } from 'react'; const SharedStateContext = createContext(); export function SharedStateProvider({ children }) { const [state, setState] = useState(false); return ( <SharedStateContext.Provider value={{ state, setState }}> {children} </SharedStateContext.Provider> ); } export function useSharedState() { return useContext(SharedStateContext); }
This pattern uses React Context to share state.
Wrap your layouts or pages with SharedStateProvider to give them access.
import { SharedStateProvider } from './SharedStateContext'; export default function RootLayout({ children }) { return ( <html lang="en"> <body> <SharedStateProvider> {children} </SharedStateProvider> </body> </html> ); }
'use client'; import { useSharedState } from './SharedStateContext'; export default function Header() { const { state, setState } = useSharedState(); return ( <header> <button onClick={() => setState(!state)}> Toggle: {state ? 'On' : 'Off'} </button> </header> ); }
This example shows how to share a dark mode setting across layouts and pages. The SharedStateProvider wraps the app. The Header toggles the mode. The Page shows the current mode and changes style accordingly.
'use client'; import { createContext, useContext, useState } from 'react'; const SharedStateContext = createContext(); export function SharedStateProvider({ children }) { const [darkMode, setDarkMode] = useState(false); return ( <SharedStateContext.Provider value={{ darkMode, setDarkMode }}> {children} </SharedStateContext.Provider> ); } export function useSharedState() { return useContext(SharedStateContext); } // RootLayout.js export default function RootLayout({ children }) { return ( <html lang="en"> <body> <SharedStateProvider> {children} </SharedStateProvider> </body> </html> ); } // Header.js 'use client'; import { useSharedState } from './SharedStateContext'; export default function Header() { const { darkMode, setDarkMode } = useSharedState(); return ( <header style={{ padding: '1rem', backgroundColor: darkMode ? '#222' : '#eee', color: darkMode ? '#eee' : '#222' }}> <button onClick={() => setDarkMode(!darkMode)} aria-label="Toggle dark mode"> {darkMode ? 'Switch to Light Mode' : 'Switch to Dark Mode'} </button> </header> ); } // Page.js 'use client'; import Header from './Header'; import { useSharedState } from './SharedStateContext'; export default function Page() { const { darkMode } = useSharedState(); return ( <main style={{ padding: '1rem', backgroundColor: darkMode ? '#333' : '#fff', color: darkMode ? '#ddd' : '#000' }}> <Header /> <p>The current mode is {darkMode ? 'Dark' : 'Light'}.</p> </main> ); }
Always wrap your app or layouts with the provider to share state properly.
Use React Context carefully; too much shared state can slow your app.
For bigger apps, consider state management libraries or server state solutions.
Shared state lets multiple layouts and pages use the same data easily.
React Context with a provider and custom hook is a simple way to share state in Next.js.
Wrap your root layout with the provider and use the custom hook inside components.