createContext を使用すると、コンポーネントが提供したり読み取ったりできるコンテキストを作成できます。

const SomeContext = createContext(defaultValue)

リファレンス

createContext(defaultValue)

コンテキストを作成するには、コンポーネントの外で createContext を呼び出します。

import { createContext } from 'react';

const ThemeContext = createContext('light');

以下の例も参照してください。

パラメータ

  • defaultValue: コンテキストを読み取るコンポーネントの上位のツリーに一致するコンテキストプロバイダがない場合に、コンテキストに持たせたい値。意味のあるデフォルト値がない場合は、null を指定してください。デフォルト値は「最後の手段」のフォールバックとして使用されることを意図しています。これは静的であり、時間の経過とともに変化することはありません。

戻り値

createContext はコンテキストオブジェクトを返します。

コンテキストオブジェクト自体はいかなる情報も保持しません。これは、他のコンポーネントが読み取りまたは提供するどのコンテキストを表します。通常、上位のコンポーネントで SomeContext.Provider を使用してコンテキスト値を指定し、下位のコンポーネントで useContext(SomeContext) を呼び出して読み取ります。コンテキストオブジェクトにはいくつかのプロパティがあります。

  • SomeContext.Provider を使用すると、コンテキスト値をコンポーネントに提供できます。
  • SomeContext.Consumer はコンテキスト値を読み取るための代替手段であり、めったに使用されません。

SomeContext.Provider

コンポーネントをコンテキストプロバイダでラップして、内部のすべてのコンポーネントに対してこのコンテキストの値を指定します。

function App() {
const [theme, setTheme] = useState('light');
// ...
return (
<ThemeContext.Provider value={theme}>
<Page />
</ThemeContext.Provider>
);
}

プロパティ

  • value:このプロバイダー内部でこのコンテキストを読み取るすべてのコンポーネントに、どれほど深くても渡したい値。コンテキストの値は任意の型にできます。プロバイダー内部でuseContext(SomeContext)を呼び出すコンポーネントは、その上にある最も内側の対応するコンテキストプロバイダーのvalueを受け取ります。

SomeContext.Consumer

useContextが存在する前は、コンテキストを読み取る古い方法がありました。

function Button() {
// 🟡 Legacy way (not recommended)
return (
<ThemeContext.Consumer>
{theme => (
<button className={theme} />
)}
</ThemeContext.Consumer>
);
}

この古い方法はまだ動作しますが、新しく記述するコードでは代わりにuseContext()でコンテキストを読み取るべきです。

function Button() {
// ✅ Recommended way
const theme = useContext(ThemeContext);
return <button className={theme} />;
}

プロパティ

  • children:関数。Reactは、useContext()と同じアルゴリズムで決定される現在のコンテキスト値を使用して、渡された関数を呼び出し、この関数から返す結果をレンダリングします。また、Reactは、親コンポーネントからのコンテキストが変更されるたびに、この関数を再実行し、UIを更新します。

使用法

コンテキストの作成

コンテキストを使用すると、コンポーネントはpropsを明示的に渡すことなく、情報を深く渡すことができます。

コンポーネントの外でcreateContextを呼び出して、1つ以上のコンテキストを作成します。

import { createContext } from 'react';

const ThemeContext = createContext('light');
const AuthContext = createContext(null);

createContextコンテキストオブジェクトを返します。コンポーネントは、それをuseContext()に渡すことによって、コンテキストを読み取ることができます。

function Button() {
const theme = useContext(ThemeContext);
// ...
}

function Profile() {
const currentUser = useContext(AuthContext);
// ...
}

デフォルトでは、それらが受け取る値は、コンテキストを作成するときに指定したデフォルト値になります。ただし、デフォルト値は決して変わらないため、それだけでは役に立ちません。

コンテキストが役立つのは、コンポーネントから他の動的な値を提供できるからです。

function App() {
const [theme, setTheme] = useState('dark');
const [currentUser, setCurrentUser] = useState({ name: 'Taylor' });

// ...

return (
<ThemeContext.Provider value={theme}>
<AuthContext.Provider value={currentUser}>
<Page />
</AuthContext.Provider>
</ThemeContext.Provider>
);
}

これで、Pageコンポーネントと、その内部の任意のコンポーネントは、どれほど深くても、渡されたコンテキスト値を「参照」します。渡されたコンテキスト値が変更された場合、Reactはコンテキストを読み取っているコンポーネントも再レンダリングします。

コンテキストの読み取りと提供、および例について詳しく読んでください。


ファイルからのコンテキストのインポートとエクスポート

多くの場合、異なるファイル内のコンポーネントは同じコンテキストにアクセスする必要があります。そのため、コンテキストを別のファイルで宣言するのが一般的です。次に、exportステートメントを使用して、他のファイルでコンテキストを利用できるようにできます。

// Contexts.js
import { createContext } from 'react';

export const ThemeContext = createContext('light');
export const AuthContext = createContext(null);

他のファイルで宣言されたコンポーネントは、importステートメントを使用して、このコンテキストを読み取ったり提供したりできます。

// Button.js
import { ThemeContext } from './Contexts.js';

function Button() {
const theme = useContext(ThemeContext);
// ...
}
// App.js
import { ThemeContext, AuthContext } from './Contexts.js';

function App() {
// ...
return (
<ThemeContext.Provider value={theme}>
<AuthContext.Provider value={currentUser}>
<Page />
</AuthContext.Provider>
</ThemeContext.Provider>
);
}

これは、コンポーネントのインポートとエクスポートと同様に機能します。


トラブルシューティング

コンテキスト値を変更する方法が見つかりません

このようなコードはデフォルトのコンテキスト値を指定します

const ThemeContext = createContext('light');

この値は決して変わりません。React は、上に一致するプロバイダが見つからない場合にのみ、この値をフォールバックとして使用します。

コンテキストを時間とともに変化させるには、状態を追加し、コンポーネントをコンテキストプロバイダでラップしてください。