How to use context api with SSR in Next.js app

Feb 11 2024
SSR is a mechanism in Next.js that receives data from the server side on each request and then passes this data to the page via props.

SSR is a mechanism in Next.js that receives data from the server side on each request and then passes this data to the page via props. This data may be required by a component that is deeply nested in the component tree hierarchy.

In a typical react application, data is passed as props from parent to child components. But if the child components are increasing over time, it becomes difficult to pass props to deeply nested components. This is called prop drilling, and this makes it hard to scale the application. This is where React’s context API comes to the rescue. It saves you from passing props at each level down and offers an effective way to access common data at each component level.

As the name implies, context is used to store values that are global, like details of an authenticated user or a blog’s tags or category if it is a blog. Some, or the other information is required at each component level and passing them as props at each level already seems cumbersome.

Context Api takes this common data away and provides an easy yet effective way for child components to access it.

Let’s take the example of an application that has a component tree structure of 4 levels namely Home, Component2, Component3 and Component4.

Suppose you are receiving the username of logged in user via the method getServerSideProps() of Next.js in the requested page, and you want to show it in the home component and Component4. Now it’s easy to show it in the home component but not in 4th one.

Let’s see the solution in the code.

import {Component2} from "../components";
import React, {createContext} from "react";

export default function Home({username}) {
    return <>
        <h1>This is component 1, {username}</h1>
        <UsernameContext.Provider value={{username}}>
            <Component2/>
        </UsernameContext.Provider>
    </>
}

export async function getServerSideProps() {
    const username = 'John' //Get from api
    return {
        props: {username},
    }
}

export const UsernameContext = createContext({})

Above is a Next.js application. We are receiving username in the method getServerSideProps() and passing it as a prop to the Home component. So, the home component can easily show the username.

Next, Component2 is not called directly but within another component called UsernameContext which is a context component declared in the last line.

Context component has two variants called Provider and consumer. You put value/object in a context by using the provider and consume that object by using the consumer. Any object placed in a context can be accessed by its child components and their downline in the tree.

import React, {useContext} from "react";
import {UsernameContext} from "./pages";

export function Component2() {
    return <>
        <h2>This is component 2</h2>
        <Component3/>
    </>
}

export function Component3() {
    return <>
        <h3>This is component 3</h3>
        <Component4/>
    </>
}

export function Component4() {
    const context = useContext(UsernameContext)
    return <h4>This is component 4, {context.username}</h4>
}

In Component4 we consume the object placed in the context by using a hook called useContext. We can also use the consumer variant of context, but this is a bit simpler. Both give the same object.