- Published on
Next.js Context API Tutorial
- Authors
- Name
- Shariq Hirani
- @ShariqHirani
Next.js Context and React Context
As Next.js is a framework built on top of React, we're able to leverage the latest features released by the team over at Facebook. One of the latest must-use features is the React Context API. In short, Next.js and React Context patterns are the same.
What is React Context
React Context, introduced in React 16.3, is a way to share props globally across the React components tree. Some use cases could be managing and passing around user state or a selected theme with the whole of the app without having to manually pass props down to each button through the component tree.
Why Do We Need React Context
Managing React props across multiple components, determining hierarchy, and forcing a convenient tree structure causes a lot of annoyance and complicated code throughout application development. With the introduction of React Hooks in React 16.8, functional programming through React became more manageable, but still lacked an integrated way to effectively manage state. This led to third-party libraries like Redux being invoked in every project. Though this was a good solution, it wasn't streamlined, led to a lot of context switching, and made it difficult for developers new to React to be able to adopt best practices across a project.
Creating React Context In a Next.js Application
Firstly, invoke a new Next.js app.
npx create-next-app
Create a directory called lib
in the root of the project and a Context file called ThemeContext.js
mkdir lib
touch lib/ThemeContext.js
Populate the ThemeContext.js
with the following
import React, { useContext, useState } from 'react'
export const themes = {
light: {
foreground: '#000000',
background: '#eeeeee',
},
dark: {
foreground: '#ffffff',
background: '#222222',
},
}
export const ThemeContext = React.createContext({
theme: undefined,
setTheme: async (theme) => null,
})
export const useTheme = () => useContext(ThemeContext)
export const ThemeProvider = ({ children }) => {
const [theme, setTheme] = useState(themes.light)
return <ThemeContext.Provider value={{ theme, setTheme }}>{children}</ThemeContext.Provider>
}
Breakdown of React Context File
import React, { useContext, useState } from "react";
imports the React project and also useContext
and userState
modules. Context is just globally set state, so it makes sense that we'll want to invoke it.
export const themes = {...}
creates some values for us to use based on the theme.
export const ThemeContext = React.createContext({...})
creates the actual Context along with holding its value. In this case, we're setting the theme's default state to themes.dark
.
export const useTheme = () => useContext(ThemeContext)
creates a hook to let subscribing components update the theme.
export const ThemeProvider = ({ children }) => {...}
creates the Provider component that can be subscribed to fetch the theme. This is what exposes our Context to the rest of the project.
const [theme, setTheme] = useState(themes.light);
set the initial state for us on load of the component itself.
The Provider Component
The Provider component allows consuming components to subscribe to context changes. Each React Context component is shipped with this. Whenever the value
prop changes, every subscriber to it will be re-rendered.
Making React Context Available To The Application
Navigate to pages/_app.js
and surround Component
with the ThemeProvider
Context Provider.
import '../styles/globals.css'
import { ThemeProvider } from '../lib/ThemeContext'
function MyApp({ Component, pageProps }) {
return (
<ThemeProvider>
<Component {...pageProps} />
</ThemeProvider>
)
}
export default MyApp
This is where the magic of Context is demystified - it's simply another component encapsulating the whole project.
Consuming Context In A Component
Navigate topages/index.js
and import the Context and then destructure the theme
and setTheme
state properties.
//...
import { useTheme } from '../lib/ThemeContext'
export default function Home() {
const { theme, setTheme } = useTheme()
const toggleTheme = () => {
setTheme(theme === themes.dark ? themes.light : themes.dark)
}
return (
//...
<main className={styles.main}>
<button
style={{
backgroundColor: theme?.background,
height: 36,
width: 256,
}}
onClick={toggleTheme}
>
ThemeContext Toggle
</button>
{/*...*/}
</main>
)
}https://reactjs.org/docs/hooks-intro.html
Run the application.
npm run dev
The Next.js landing page is updated with a button at the top that will toggle and adopt the theme upon click.