Reactを使ってプログラミングをするとき、データをコンポーネント間で共有する方法が必要になることがあります。
そのための便利なツールがuseContext
というものです。
この記事では、useContext
の使い方とそのメリット、注意点についてわかりやすく解説します。
React Hooksとは?
React Hooksとは、Reactのバージョン16.8から導入された新機能で、関数型コンポーネントでステートやライフサイクルといった機能を使うことができるようになりました。useState
やuseEffect
などがよく知られていますが、今回はその中の一つ、useContext
について詳しく見ていきましょう。
ReactのuseContextとは?
useContext
は、Reactのコンテキスト(Context)を関数型コンポーネントで使うためのHookです。
これを使うと、親コンポーネントから子コンポーネントへとデータを渡すときに、中間のコンポーネントを経由せずに直接データを渡すことができます。
useContextのメリット
useContext
の最大のメリットは、コンポーネント間でデータを簡単に共有できることです。
これにより、親コンポーネントから子コンポーネントへとデータを渡すときに、中間のコンポーネントを経由せずに直接データを渡すことができます。
これは、大規模なアプリケーションで特に有用です。
また、useContext
を使うと、グローバルな状態を管理することができます。
これにより、アプリケーション全体で共有する必要があるデータ(例えば、ログインユーザーの情報やテーマの設定など)を簡単に管理することができます。
useStateとの違いは?
useState
とuseContext
は、どちらもReact Hooksの一部であり、関数型コンポーネントでステートを扱うためのものです。
しかし、それぞれが扱うステートの範囲が異なります。
useState
は、一つのコンポーネント内でのステートを扱います。
つまり、useState
を使って作成したステートは、そのコンポーネント内でのみアクセス可能です。
一方、useContext
は、複数のコンポーネント間でステートを共有するためのものです。
つまり、useContext
を使って作成したステートは、そのコンテキストを使っているすべてのコンポーネントでアクセス可能です。
useContextの使い方
まずは、useContext
の基本的な使い方から見ていきましょう。
import React, { useContext } from 'react';
const MyContext = React.createContext();
function MyComponent() {
const value = useContext(MyContext);
return <p>受け取ったデータ: {value}</p>;
}
function App() {
return (
<MyContext.Provider value="こんにちは、世界!">
<MyComponent />
</MyContext.Provider>
);
}
export default App;
このコードでは、まずReact.createContext()
を使って新しいコンテキストを作成しています。
そして、MyContext.Provider
コンポーネントを使って、そのコンテキストに値を設定します。
この値は、value
属性を使って設定します。
そして、useContext(MyContext)
を使って、そのコンテキストの値を取得します。
この値は、MyContext.Provider
で設定した値となります。
【具体例】useContextを使ったテーマ切り替えの実装
ここでは、useContext
を使ってテーマ(ライトモードとダークモード)を切り替える機能を実装する例を見てみましょう。
import React, { useContext, useState } from 'react';
const ThemeContext = React.createContext();
function MyComponent() {
const { theme, toggleTheme } = useContext(ThemeContext);
return (
<div style={{ backgroundColor: theme === 'dark' ? 'black' : 'white', color: theme === 'dark' ? 'white' : 'black' }}>
<p>現在のテーマ: {theme}</p>
<button onClick={toggleTheme}>テーマ切り替え</button>
</div>
);
}
function App() {
const [theme, setTheme] = useState('light');
const toggleTheme = () => {
setTheme(prevTheme => prevTheme === 'light' ? 'dark' : 'light');
};
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
<MyComponent />
</ThemeContext.Provider>
);
}
export default App;
このコードでは、ThemeContext
というコンテキストを作成し、その中にtheme
とtoggleTheme
という2つの値を持たせています。
そして、MyComponent
コンポーネントでは、そのコンテキストの値を取得し、それを使ってテーマを切り替える機能を実装しています。
useContextで複数の値を扱う
useContext
は、一つの値だけでなく、複数の値を扱うこともできます。
そのためには、コンテキストの値をオブジェクトにすることで、そのオブジェクトの中に複数の値を持たせることができます。
import React, { useContext } from 'react';
const MyContext = React.createContext();
function MyComponent() {
const { message, author } = useContext(MyContext);
return (
<div>
<p>メッセージ: {message}</p>
<p>作者: {author}</p>
</div>
);
}
function App() {
return (
<MyContext.Provider value={{ message: 'こんにちは、世界!', author: '太郎' }}>
<MyComponent />
</MyContext.Provider>
);
}
export default App;
このコードでは、MyContext.Provider
のvalue
属性にオブジェクトを設定しています。
そして、useContext(MyContext)
を使ってそのオブジェクトを取得し、その中のmessage
とauthor
の値を取り出しています。
useContextの注意点
useContextを使う場所
useContext
は、関数コンポーネントのトップレベルで呼び出す必要があります。
つまり、ループや条件分岐、ネストした関数の中でuseContext
を呼び出すことはできません。
例えば、以下のようなコードはエラーになります。
function MyComponent() {
const value = 0;
if (value === 0) {
const contextValue = useContext(MyContext); // これはエラーになります
}
// ...
}
このコードでは、if
文の中でuseContext
を呼び出そうとしていますが、これはReactのルールに違反しているためエラーになります。
useContextのパフォーマンスについて
useContext
を使うとき、パフォーマンスに影響を及ぼす可能性があります。
なぜなら、コンテキストの値が変更されると、そのコンテキストを使っているすべてのコンポーネント
が再レンダリングされるからです。
例えば、以下のようなコードを考えてみましょう。
import React, { useContext, useState } from 'react';
const MyContext = React.createContext();
function MyComponent() {
const { message } = useContext(MyContext);
return <p>メッセージ: {message}</p>;
}
function App() {
const [count, setCount] = useState(0);
return (
<MyContext.Provider value={{ message: 'こんにちは、世界!', count }}>
<MyComponent />
<button onClick={() => setCount(count + 1)}>カウントアップ</button>
</div>
);
}
export default App;
このコードでは、MyComponent
コンポーネントはMyContext
のmessage
の値を使っています。
しかし、MyContext.Provider
のvalue
にはcount
の値も含まれています。
そのため、count
の値が変更されると、MyComponent
コンポーネントも再レンダリングされます。
これは、MyComponent
コンポーネントがcount
の値を使っていないにも関わらず、再レンダリングが発生するため、パフォーマンスに影響を及ぼす可能性があります。
この問題を解決するためには、異なる値を扱うための別々のコンテキストを作成すると良いでしょう。
React を効率的に身につける勉強法は?
React には興味があっても、プログラミング学習をはじめたばかりであれば、以下のような疑問を持つかもしれません。
- Reactエンジニアとして活躍するために何をすればいい?
- 何から勉強すればいいんだろう?
- 絶対に転職を成功させるには?
React は習得が比較的難しいため、勉強法の選び方を間違うと時間・労力・お金が無駄になってしまいます…。
そのため、こちらの記事を参考に、ご自身に最適な学習方法を選んでみませんか?