Next.jsでReact.ContextでState管理する実装方法についてまとめました。
目次
Contextの初期化 – createContext
最小限のContext作成の実装はこんな感じ。
pages/_app.tsxに以下の実装をします。createContextなどは通常のReactと変わらないです。
_app.tsxがexport defaultするコンポーネントは各ページのルートコンポーネントです。Componentが各ページの内容になります。ここにContext.Providerを設定することで全域でContextが使えるようになります。
設計や好みによりますが、AppContextは外に出してもいいかもしれません。
import React, { Dispatch, useState } from "react"
export const AppContext = React.createContext(
{} as {
count: number;
setCount: Dispatch<React.SetStateAction<number>>;
}
)
export default function MyApp({Component, pageProps}) {
const [count, setCount] = useState(0)
return (
<AppContext.Provider value={{count, setCount}}>
<Component {...pageProps} />
</AppContext.Provider>
)
}
Contextの使用 – useContext
useContextでContextを使用する箇所はReactとの差分はないです。
通常通りuseContext(createContextした値)で値を取得できます。
import Link from "next/link";
import { useContext } from "react";
import Layout from "../components/Layout";
import { AppContext } from "./_app";
const IndexPage = () => {
const {count, setCount} = useContext(AppContext)
return (
<Layout title="Home | Next.js + TypeScript Example">
<h1>Hello Next.js 👋</h1>
<br />
<p>
{count}
<Link href="/about">
<a>About</a>
</Link>
</p>
<button onClick={() => setCount(count+1)}>count up</button>
</Layout>
);
};
export default IndexPage;
サーバーサイド(getServerSideProps)でContext参照はできない
試しにこんな感じの実装で、サーバーサイド側(getServerSideProps)でContextを取得したりする処理をやってみましょう。
import Link from "next/link";
import { useContext } from "react";
import Layout from "../components/Layout";
import { AppContext } from "./_app";
export const getServerSideProps = async (context) => {
const {count, setCount} = useContext(AppContext)
console.log(count);
setCount(count + 1)
return new Promise((resolve) => setTimeout(() => resolve({props: {}}), 1000))
};
...
Reactのhooksはコンポーネント内で実装しろと怒られます。
Contextはクライアント側で保持するグローバルなStateなので当然ですね。

Next.jsのSSRのサーバーサイドの動作の仕組みについてはこちらで説明しているのでよかったら見てみてください!