# Using React Context API with NextJS

One huge pain point in React (and NextJS) is having to pass props through multi-level components. The bigger the application or project gets, the more painful this becomes. This is because of how React is structured, in a tree like fashion with data only flowing in one direction.

There are multiple ways to solve this with things like

- React Redux
- MobX
- ...and more

One of the newer ways, especially introduced with React Hooks, is the React Context API.

# What is the Context API?
> It is a way to enable multiple components (or pages in NextJS) to share global variables and data without having to "pass" these as props. Think of it like a global "object" which stores data.

Although the Context API can be used for most cases, it shouldn't be used for **everything**. A close observation on component re-renders should be taken when using Context API to prevent any compromising leaks or inefficiencies.

That being said, we can easily implement Context API using React Hooks into **NextJS**.

_Let's step through the creation of a simple custom Auth to allow our NextJS app to see the logged in status of a user, and the users details throughout every component and page._

## 1. Creating a **Provider** component

This component will **provide** our defined data to the rest of our app.

```
import { useState, createContext } from "react";

export const AuthContext = createContext();

const AuthProvider = ({ children }) => {

	const [ loggedIn, setLoggedIn ] = useState(false);
	const [ userDetails, setUserDetails ] = useState([]);

	const login = value => {

		setLoggedIn(true);
		setUserDetails({
			name: "Alan",
			notifications: 3
		});
	}

	const logout = value => {

		setLoggedIn(false);
		setUserDetails([]);
	}

	const contextValue = {

		status: {

			loggedIn,
			login,
			logout
		},
		user: {

			userDetails,
			setUserDetails
		}
	};

	return (
		<AuthContext.Provider value={ contextValue }>
			{ children }
		</AuthContext.Provider>
	);
};

export default AuthProvider;
```
- The `createContext()` method, allows us to create a context object to hold some global data.
- I've set up some state variables using the [useState hook](https://blog.alanmontgomery.co.uk/how-to-use-the-usestate-hook-in-react), including a variable for logged in, and a variable for the user details.
- Custom login/logout functions created to set the *logged in status* and also the user details (for this example, when logging in, we just mimic it with hard-coded values).
- I've set up a `contextValue` object which we can use to structure our global data nicely, for example, for the `loggedIn` variable and functions, I've called it *status*, which means, further down the React Tree of components we will be able to access the loggedIn state variable like `AuthContext.status.loggedIn` which we will see shortly.
- A Provider component will always return the children, in our case, the children will be the component or page, wrapped with our `AuthContext.Provider`.

We can save this Provider in a `providers` folder or `utils` or anything you like.


## 2. Wrap our app root component with our Context

In traditional React, we would wrap our `<App />` with the Context, however, in NextJS, this doesn't exist. Instead we can provide a custom App component by creating a file in the root folder called `_app.js`, it should already be present in most cases.

Let's first import our `AuthProvider` component:
```
import AuthProvider from "../utils/AuthProvider";
```

Then wrap our `<Component .... />` with this Provider. At this point then the Component will be passed as a child to our Context API Provider, which we saw above with the return of children.

```
return (

	<AuthProvider>
		<Component { ...pageProps } />
	</AuthProvider>
);
```

## 3. Import useContext and our custom AuthContext into index.js

In order to use the values from our Provider, we need to utilise the `useContext` hook from React, as well as importing our `AuthContext` we created earlier:
```
import { useContext } from "react";
import { AuthContext } from "../utils/AuthProvider";
```
Inside our Home (or any other) component/page we can easily grab all of our Context global variables using the above hook, and destruct our custom, nicely formatted values like this:
```javascript
const { status, user } = useContext(AuthContext);
```
At this point, we now have access, globally to the variables we set up earlier, e.g. `{ status.loggedIn }` will return the loggedIn value held in that state variable.

## 4. Setting up a simple login / logout UI

Using our global Context API variables/functions and data, we can now manipulate our UI based on this, let's set up a very basic, mimicked example of this:

> Example of our return in index.js

```
<main className={styles.main}>
	<h1 className={styles.title}>
		Welcome to <a href="https://nextjs.org">Next.js!</a>
	</h1>

	<h4>
		Status:&nbsp;
		<span style={{ color: status.loggedIn ? "green" : "red" }}>
			{ status.loggedIn ? "Logged in" : "Not Logged In" }
		</span>
	</h4>

	{ status.loggedIn && <button onClick={ status.logout }>Logout</button> }
	{ !status.loggedIn && <button onClick={ status.login }>Login</button> }

	{ status.loggedIn &&
		<h3>Hi { user.userDetails.name }</h3>
	}
</main>
```

Logged out state:
![NextJS logged out state](https://i.ibb.co/bXWrfSc/Screenshot-2020-11-01-at-22-48-12.png)

Logged in state:
![NextJS logged in state](https://i.ibb.co/b39zs5T/Screenshot-2020-11-01-at-22-48-22.png)

Keep in mind, our Context API global "object" or data is accessible by every page/component. So in this case, if we were to navigate to `/account` for example, the state would be retained and accessible in the same, global way.

This was a very very basic example of how to set up a Context API provider, and inject it into our NextJS app, then use the accessible functions and data based on the state, I hope this helps anyone, if it did, leave a little reaction on this post, greatly appreciated!

I've also recently started a YouTube channel. I'd love to see you over there and I welcome new subscribers. I'm posting coding tutorials, mostly on JavaScript, React and NextJS! 👇👇👇👇

[Alan Montgomery - Coding Tutorials](https://bit.ly/alanmontgomerycoding)

%[https://bit.ly/alanmontgomerycoding]

Thanks for reading! Leave a comment below if you liked this!
