Context

Framework Next.js 13 Data Sharing: Context

Next.js 13 Context API

Rendering: Server and Client Components | Next.js

After Next.js 13, the js components are ALL treated as the server-side component by default.

So if you want to use the client-side function such as createContext, useContext, useState that you have to write 'use client'; on the top of the file to tell the Next.js 13 that this component is the client-side component

1. Create Global Context Store File

Next.js 13 Context API Tutorial - YouTube

Write the 'use client'; on the top of the context file to tell the Next.js 13 that this component is the client-side component

// app/Context/GlobalContext.tsx
'use client';

import { createContext, useContext, Dispatch, SetStateAction, useState } from "react";

type DataType = {
    firstName: string
}

interface ContextProps {
    userId: string,
    setUserId: Dispatch<SetStateAction<string>>,
    data: DataType[],
    setData: Dispatch<SetStateAction<DataType[]>>
}

const GlobalContext = createContext<ContextProps>({
    userId: '',
    setUserId: (): string => '',
    data: [],
    setData: (): DataType[] => [] 
})

export const GlobalContextProvider = ({ children }) => {
    const [userId, setUserId] = useState('');
    const [data, setData] = useState<[] | DataType[]>([]);
    
    return (
        <GlobalContext.Provider value={{ userId, setUserId, data, setData }}>
            {children}
        </GlobalContext.Provider>
    )
};

export const useGlobalContext = () => useContext(GlobalContext);

2. Add Global Context to the app/layout.tsx

Because app/layout.tsx is the server-side component by default so you CAN NOT use the client-side function in the app/layout.tsx

But it can import the client-side context component then use it.

// app/layout.tsx
import './globals.css';
import { GlobalContextProvider } from './Context/GlobalContext';

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      {/*
        <head /> will contain the components returned by the nearest parent
        head.tsx. Find out more at https://beta.nextjs.org/docs/api-reference/file-conventions/head
      */}
      <head />
      <body>
        <GlobalContextProvider>
          {children}
        </GlobalContextProvider>
      </body>
    </html>
  )
}

3. Use Global Context on the app/page.tsx

Now we can use the context on the children client-side component

// app/page.tsx
'use client';

import { useEffect } from 'react';
import { useGlobalContext } from './Context/GlobalContext';
import styles from './page.module.css';

export default function Home() {
  const { userId, setUserId, data, setData } = useGlobalContext();

  useEffect(() => {
    setUserId('2');
    setData([
      { firstName: 'Tim' }, 
      { firstName: 'Kyle' }, 
      { firstName: 'Michael' }
    ]);
  }, [])

  return (
    <div className={styles.container}>
      <p>{userId}</p>
      <p>List:</p>
      {data.map((e, i) => <p key={i}>{e.firstName}</p>)}
    </div>
  )
}

Reference