DEV Community

Mohammed Nadeem Shareef
Mohammed Nadeem Shareef

Posted on

Context API with TypeScript and Next.JS

How to write context API with TypeScript and next.JS

Photo by [Pakata Goh](https://unsplash.com/@pakata?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/developer?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)

Why we need context?

In a typical React application, data is passed top-down (parent to child) via props, but such usage can be cumbersome for certain types of props (e.g. locale preference, UI theme) that are required by many components within an application. Context provides a way to share values like these between components without having to explicitly pass a prop through every level of the tree. read more

What is contextAPI?

Context provides a way to pass data through the component tree without having to pass props down manually at every level.

So, now we know why we need context and what is context let's dive into the coding part.

Before starting, set up a basic version of the nextJS app with typescript

npx create-next-app context-api
npm install --save-dev typescript @types/react
Enter fullscreen mode Exit fullscreen mode

Create a folder called context, here we will store all the different contexts. For now, create an AuthContext.tsx file

Step 1:- Create context type

Inside AuthContext.tsx.
As we are using TypeScript we have to create types for our context

type authContextType = {
    user: boolean;
    login: () => void;
    logout: () => void;
};
Enter fullscreen mode Exit fullscreen mode

Step 2:- Create context default values

const authContextDefaultValues: authContextType = {
    user: null,
    login: () => {},
    logout: () => {},
};
Enter fullscreen mode Exit fullscreen mode

Step 3:- createContext & useContext

const AuthContext = createContext<authContextType>(authContextDefaultValues);

export function useAuth() {
    return useContext(AuthContext);
}
Enter fullscreen mode Exit fullscreen mode

Step 4:- Create a provider function

type Props = {
    children: ReactNode;
};

export function AuthProvider({ children }: Props) {
    const value = {

    }
    return (
        <>
            <AuthContext.Provider value={value}>
                {children}
            </AuthContext.Provider>
        </>
    );
}
Enter fullscreen mode Exit fullscreen mode

We will wrap this AuthProvider function, where we want to use our context, and the value prop will have the values of authContextType. We will fill up values in the next step.

Step 4:- Fill up values

export function AuthProvider({ children }: Props) {
    const [user, setUser] = useState<boolean>(null);

    const login = () => {
        setUser(true);
    };

    const logout = () => {
        setUser(false);
    };

    const value = {
        user,
        login,
        logout,
    };

    return (
    ...
Enter fullscreen mode Exit fullscreen mode

Now our context is ready to use.

Step 5:- Enable AuthProvider

First, we have to enable AuthProvider, to do so edit the default _app.js file like so

import { AuthProvider } from "../context/AuthContext";
import "../styles/globals.css";

function MyApp({ Component, pageProps }) {
    return (
        <>
            <AuthProvider>
                <Component {...pageProps} />
            </AuthProvider>
        </>
    );
}

export default MyApp;
Enter fullscreen mode Exit fullscreen mode

Step 6:- Using context

Now remove all the template nextJS generate and simply import the context

import Head from "next/head";
import styles from "../styles/Home.module.css";
import { useAuth } from "../context/AuthContext";

export default function Home() {
    const { user, login, logout } = useAuth();

    return (
        <div className={styles.container}>
            <Head>
                <title>Context-api with TypeScript and nextJS</title>
                <link rel="icon" href="/favicon.ico" />
            </Head>
            <main className={styles.main}>
                <div>
                    <h1>Hello Context</h1>
                    <h2>User: {user ? "login" : "logout"}</h2>
                    <div>
                        <button onClick={login}>Login</button>
                        <button onClick={logout}>Logout</button>
                    </div>
                </div>
            </main>
        </div>
    );
}

Enter fullscreen mode Exit fullscreen mode

Okay many things happen here let me break it down, first we import the context hook "useAuth" then inside our Home() we destructure all the values from "useAuth" then we use it as per our requirement.

See the live demo
Github repo

My portfolio
Linkedin
twitter

Top comments (16)

Collapse
 
cheedie6 profile image
Cheedie

Hi. Good day. I went through your article and it was very infomative and got me started on using context in next js and typescript. I encountered an error while setting up. Please would you help me look at it to know what i did wrong.
This is the error i am getting when assigning value in the provider

Type '(ContextType | Dispatch>)[]' is missing the following properties from type 'ContextType': currentPage, numberofItemstoDisplayts(2739)
index.d.ts(331, 9): The expected type comes from property 'value' which is declared here on type 'IntrinsicAttributes & ProviderProps'

Collapse
 
shareef profile image
Mohammed Nadeem Shareef

I would be helpful if you send a repo that have this issue so that I can look into it.

Collapse
 
cheedie6 profile image
Cheedie

unfortunately it is a work repo so it is private. Please is there another way i can send it to you. Do you mind having a google meet call with me?

Thread Thread
 
shareef profile image
Mohammed Nadeem Shareef

Okay. Let's connect on LinkedIn. My LinkedIn profile

Collapse
 
itzsrikanth profile image
itzsrikanth

A very informative article.
But having one doubt of how context persists across different pages since NextJs does not act as a SPA?

Collapse
 
muswain profile image
Mrutyunjay

As long as the provider is wrapped in the MyApp function in _app.tsx, it basically is available across pages. The provider is basically the parent of all components including all next.js pages in the way it is specified in _app.tsx file.

Collapse
 
shareef profile image
Mohammed Nadeem Shareef

I am not sure but I think NextJS handles it under the hood, I have used context in NextJS projects and It was persists across different pages.

Collapse
 
vishal2369 profile image
Vishal2369

It was informative.
Thanks

Collapse
 
shareef profile image
Mohammed Nadeem Shareef

Glad it helps ☺️

Collapse
 
pion_devel_94c71e56547785 profile image
Pion Devel

Hi Nadeem,

My name is Liady fouad and I'm a junior front end developer from Italy. So I'm building a web app with Next 13, Firebase and Open Ai API.This is actually my first project on Next js. I was using Next auth to get data and encounter some problems retrieving the UID. So i switch to firebaseAuth but got blocked there also. I read your article about how to authenticate with with google and Next js and found it very interesting .

So i have several problems with my project:I want to get the UID first and i want to integrate stripe to get subscription plans.

I was wondering if you can take a look at my code and help me out with these problems. I can pay 5$ to 10$ per hour.

Please let me know if you’re interested(I really need helpπŸ€—).

Thanks again

Collapse
 
niyongaboeric profile image
NiyongaboEric • Edited

Well articulated and helped me getting started with Typescript, NextJS and React Context API. Keep it up brother.

Collapse
 
shareef profile image
Mohammed Nadeem Shareef

Nice to hear it.πŸ˜„
Follow for new blogs!

Collapse
 
krivoo3 profile image
OCTANE πŸ’€

How do you pass properties to the logout methods?

Collapse
 
shareef profile image
Mohammed Nadeem Shareef

As we are using typescript first set the type of arguments


type authContextType = {
    user: boolean;
    login: () => void;
    logout: (someParameter: any) => void;
};

Enter fullscreen mode Exit fullscreen mode

then pass make use of your properties


const logout = (someParameter: any) => {
        // use of your parameters
        setUser(false);
};

Enter fullscreen mode Exit fullscreen mode

And finally pass it to the function, where you are using it.

...
<div>
    <button onClick={login}>Login</button>
    <button onClick={() => logout(someProperty)}>Logout</button>
</div>
...
Enter fullscreen mode Exit fullscreen mode
Collapse
 
surafelgetachew profile image
Surafel Getachew

Great!

Collapse
 
shareef profile image
Mohammed Nadeem Shareef

Thanks! πŸ˜‡

Collapse
 
ayahosnym profile image
Aya Hosny • Edited

thanks a lot but If we have a lot of context files
put all of them in myApp file?