React ContextはReduxのようにグローバルなデータの定義と参照ができるReactのAPIです。
React Contextには「Reduxなしでグローバルなデータの定義ができる」「Props drillingと呼ばれる、いわゆるpropsのバケツリレー問題を解決できる」などのメリットがあります。
Contextを作成し、useContextで値を参照するための手順は以下の通りです。
- Providerコンポーネントを作成する
- ProviderコンポーネントでContext利用対象のコンポーネントを囲む
- Contextをコンポーネントから呼び出す
以下では具体例を交えながら各手順について紹介します。
Providerコンポーネントを作成する
Providerコンポーネントでやることは以下の通りです。
- createContextでContextを作成する
- createContextで作成されたContextをexportし、他のコンポーネントから参照できるようにする
- Providerコンポーネントのvalueプロパティに他のコンポーネントから参照したい値をセットする
具体例は以下の通りです。
src/components/shared/ExampleProvider.tsx
import React, { createContext, FC, ReactNode } from "react";
type Props = {
children: ReactNode;
};
const defaultMessage = "Hi";
export const ExampleContext = createContext<string>(defaultMessage);
export const ExampleProvider: FC<Props> = ({ children }) => {
return (
<ExampleContext.Provider value={defaultMessage}>
{children}
</ExampleContext.Provider>
);
};
createContext<string>
の<string>
はジェネリックメソッド(ジェネリック関数)と呼ばれるものです。今回の場合はジェネリックメソッドを利用してContextの型をString型に指定しています。
ジェネリクスの詳細解説は【TypeScript】ジェネリクス(Generics)入門。ジェネリクスの種類と利用例で紹介しています。
ProviderコンポーネントでContext利用対象のコンポーネントを囲む
今回の場合ですと<ExampleProvider>
でコンポーネントを囲みます。
任意のコンポーネントでContextを利用したい場合は_app.tsx
にProviderコンポーネントを追記します。
_app.tsx
import "../../styles/globals.css";
import type { AppProps } from "next/app";
import { ExampleProvider } from 'src/components/shared/ExampleProvider';
function MyApp({ Component, pageProps }: AppProps) {
return (
<ExampleProvider>
<Component {...pageProps} />
</ExampleProvider>
);
}
export default MyApp;
Contextをコンポーネントから呼び出す
Contextの呼び出し方法は以下の通りです。
- Providerコンポーネントで作成されたContextをimportする
- importしたContextをuseContextの引数にする
useContextの戻り値がProviderコンポーネントのvalueプロパティの値になります。
src/pages/index.tsx
import type { NextPage } from "next";
import { ExampleContext } from "src/components/shared/ExampleProvider";
import { useContext } from "react";
const Home: NextPage = () => {
const message = useContext(ExampleContext);
return <>{message}</>; // 画面には"Hi"と表示される
};
export default Home;
さいごに
Twitter(@nishina555)やってます。フォローしてもらえるとうれしいです!