React Context API is a powerful feature which enables to management and shares state information across various sections of the Next js application. Using Context API we can share data without passing the props down manually at every level for same.
In this guide, we will discuss how to set up and use Context API with various use cases using practical examples in the Next js application.
[lwptoc]
What is the React Context API?
In React js, the Context API is a state management tool which comes inside the library bundle. It helps to create a way to manually pass data through the component tree via props. It provides an efficient way to make it possible to share data or manage states between various React or Next js components in large applications.
Setting Up the Context API in Next.js
We will follow these steps and discuss how to easily implement it in Next js application:
Step 1: Create a Context File
Step 2: Wrap the Application with the Context Provider
Step 3: Use the Context in Your Components
Step 1: Create a Context File
To set up the Context API, first, we will create a context.js file in our Next js project’s context folder. So that the path of the file will be ~context/context.js.
This file will contain the context and the state that we can share across our application:
import { createContext, useState } from "react";
export const MessageContext = createContext(null);
function MessageProvider({ children }) {
const [message, setMessage] = useState();
return (
<MessageContext.Provider value={{ message, setMessage }}>
{children}
</MessageContext.Provider>
);
}
export default MessageProvider;
We created a context called MessageContext
and a context provider MessageProvider
which uses the useState
hook to create a state variable message
and its setter function named setMessage
. Then these are passed as values to the MessageContext.Provider
.
Step 2: Wrap the Application with the Context Provider
Thereafter, we need to wrap the application without a context provider. Open the _app.js file which is the main component in a Next js application then make following changes:
import MessageProvider from "../context/MessageContext";
function MyApp({ Component, pageProps }) {
return (
<MessageProvider>
<Component {...pageProps} />
</MessageProvider>
);
}
export default MyApp;
Step 3: Use the Context in Your Components
Finally, we can use the useContext
hook to access the context in various other components. Here is an example:
import { useContext } from "react";
import { MessageContext } from "../context/MessageContext";
function MyComponent() {
const { message, setMessage } = useContext(MessageContext);
// You can now use `message` and `setMessage` in your component
}
In above example, we have import the useContext
hook and the MessageContext
from our context.js
file. We are then calling useContext
with MessageContext
as an argument to access the message
state and the setMessage
function.
Advanced Usage of Context API in Next.js
After discussing some of the basic implementations of Context API, let’s have a look on further at advanced use-cased and how it can help us in intensive and large applications:
1. Combining Multiple Contexts
In large applications, we can have multiple contexts to manage states related to different information for example you might have one context for user data, theme settings and another for application settings.
In that case, this is how you can combine multiple contexts:
Following is a sample context named User Context in file ~context/UserContext.js:
import { createContext, useState } from "react";
export const UserContext = createContext(null);
function UserProvider({ children }) {
const [user, setUser] = useState(null);
return (
<UserContext.Provider value={{ user, setUser }}>
{children}
</UserContext.Provider>
);
}
export default UserProvider;
Similarly, we have created another context to keep the theme-related context in file ~context/ThemeContext.js:
import { createContext, useState } from "react";
export const ThemeContext = createContext(null);
function ThemeProvider({ children }) {
const [theme, setTheme] = useState("light");
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
{children}
</ThemeContext.Provider>
);
}
export default ThemeProvider;
Let’s have a look , at how to use and compile both above contexts in the ~pages/_app.js:
import UserProvider from "../context/UserContext";
import ThemeProvider from "../context/ThemeContext";
function MyApp({ Component, pageProps }) {
return (
<UserProvider>
<ThemeProvider>
<Component {...pageProps} />
</ThemeProvider>
</UserProvider>
);
}
export default MyApp;
In this setup, both the UserContext
and ThemeContext
are available to all the components in the application.
2. Using Context with useReducer
To manage more complex state logic, the useReducer
hook proves better than useState
hook which we used earlier.
The useReducer
allows to handle multiple states in a more organised way. Let’s have a look at how we can use useReducer
in the context file ~context/AppContext.js:
import { createContext, useReducer } from "react";
export const AppContext = createContext(null);
const initialState = {
count: 0,
};
function reducer(state, action) {
switch (action.type) {
case "increment":
return { count: state.count + 1 };
case "decrement":
return { count: state.count - 1 };
default:
throw new Error();
}
}
function AppProvider({ children }) {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<AppContext.Provider value={{ state, dispatch }}>
{children}
</AppContext.Provider>
);
}
export default AppProvider;
In the above example, we used useReducer
to manage a count
state and dispatch
function is used to update the state based on the action type.
3. Using createContext with TypeScript
When we use createContext
with TypeScript, we can provide a type for the context value which will allow TypeScript to type-check the value passed to the Provider and the value returned from useContext
.
Here is how to do it:
import React, { createContext, useContext } from 'react';
interface ContextType {
message: string;
setMessage: (message: string) => void;
}
const MessageContext = createContext<ContextType | undefined>(undefined);
const MessageProvider: React.FC = ({ children }) => {
const [message, setMessage] = useState("Hello, world!");
return (
<MessageContext.Provider value={{ message, setMessage }}>
{children}
</MessageContext.Provider>
);
};
function useMessageContext() {
const context = useContext(MessageContext);
if (!context) {
throw new Error("useMessageContext must be used within a MessageProvider");
}
return context;
}
In the above typescript example, we defined an ContextType
interface which describes the type of the context value.
Conclusion
The Context API is a useful and powerful state management tool for the Next js application. Context API allows us to pass the data efficiently without any dependency on passing the data as props manually.
We also discussed how to easily setup Context API in the Next js application and also discussed advanced use cases also how we can deploy useReducer
hook instead of useState
.
Make sure you pick the best use-case based on the architecture of your application. Using the simple context API also suffices the requirement but for advanced and large-scale applications we can user useReducer
hook if required. Hope this will be helpful.
Leave a Reply