React HookのuseContextは何ができるの?
useContextを使うことでデータをグローバルに扱うことができるよ!
Hookとは?
Hook(フック)とはReact 16.8のバージョンで新しくで追加された機能です。
Hookは関数コンポーネントで使うことができる機能で、クラスを書かなくてもstateなどの機能を使えるようになります。
useContextはHookの1つの機能です。
useContextとは?
「useContext
」は下の階層のコンポーネント(子コンポーネント)とデータの共有を行うときに使うフックです。
通常、親コンポーネントから子コンポーネントにデータを渡すときは、propsを介して行います。
しかし、親から子、そのまた子といったように複数のコンポーネントを介してデータを渡すpropsではデータの渡し方が煩雑になります。
useContextはそのような煩雑なやり取りをせずに、データを渡すことができます。
useContextの使い方
親コンポーネントと子コンポーネントでの設定が異なるから、
それぞれ解説していくね!
親コンポーネントでの設定
まずはuseContextの機能をインポートします。
インポートしなくても使えますが、 今回はインポートをして使っていきます。
import React, { createContext } from 'react';
インポートができたらuseContextを使うことができるようになります。
インポートしたcreateContext
を使ってcontextを作成します。
作成したcontextの名前は大文字から始まるようにしましょう。
export const CountContext = createContext();
親コンポーネントで作成したCountContextを子コンポーネントで扱えるようにexportをしています。
子コンポーネントではこのCountContextをimportすることになります。
次に作成したcontextオブジェクトを子コンポーネントに渡すための処理を記述します。
少し独特な記述になるので詳しく解説していきます。
まずは作成したCountContextにProvider
を用いてCountContext.Provider
のように記述します。
そして、続けてvalue
の値を指定します。valueの値は子コンポーネントに共有したい値を指定します。
これらの記述は決り文句だと思って下さい。
<CountContext.Provider value={10}>
</ CountContext.Provider>
<CountContext.Provider>
で子コンポーネントを囲むことによって、Providerで指定したvalueの値を子コンポーネントで扱えるようになります。
<CountContext.Provider value={10}>
<子コンポーネント />
</ CountContext.Provider>
まとめると親コンポーネントではこのようになります。
import React, { createContext } from 'react';
// Contextの作成
export const CountContext = createContext();
export const ParentComponent = () => {
return (
<div>
<CountContext.Provider value={10}>
<ChildComponentC />
</CountContext.Provider>
</div>
);
}
子コンポーネントでの設定
親コンポーネントから渡されたデータを子コンポーネントで扱う方法です。
まずはcontextを使えるように、useContext
をインポートします。
こちらもインポートしなくても使えます。
import { useContext } from 'react';
続いて親コンポーネントで作成したcontextをインポートします。
import { CountContext } from './ParentComponent';
インポートしたものを使ってProviderのvalueで設定した値を受け取ります。
これで子コンポーネントでcountのデータを取得できました。
const count = useContext(CountContext);
まとめると子コンポーネントではこのようになります。
import React, { useContext } from 'react';
import { CountContext } from './ParentComponent';
export const ChildComponentC = () => {
// 親コンポーネントで設定した値を受け取る
const count = useContext(CountContext);
return (
<div>
<p>カウント: {count}</p>
</div>
)
}
親コンポーネントで渡された値を子コンポーネントで受け取り表示することができました。
親コンポーネントと子コンポーネントでは設定が違うから
注意が必要だね!
useStateを使った方法
useStateと一緒に使うことが多いよ!
useContextはstateを子コンポーネントに渡すことができます。
ReactではuseStateを渡すことが頻繁にあるので、useStateを使った方法を解説していきます。
親コンポーネント
useState
とcreateContext
をインポートしてcontextを作成します。
import React, { useState, createContext } from 'react';
export const CountContext = createContext();
useStateを作成してProviderのvalueにstateを指定します。
Providerで囲まれた子コンポーネントは親コンポーネントで使っているstateを管理できるようになります。
const [count, setCount] = useState(0);
<CountContext.Provider value={{count, setCount}}>
<子コンポーネント />
</CountContext.Provider>
まとめるとこのようになります。
import React, { useState, createContext } from 'react';
// Contextの作成
export const CountContext = createContext();
export const ParentComponent = () => {
const [count, setCount] = useState(0);
return (
<div>
<CountContext.Provider value={{count, useCount}>
<ChildComponentC />
</CountContext.Provider>
</div>
);
}
useStateとuseContextを組み合わせて使うことで、コンポーネントをまたいだ状態管理を行うことができます。
子コンポーネント
useContext
を使えるようにインポートして、親コンポーネントからcontextをインポートします。
import { useContext } from 'react';
import { CountContext } from './ParentComponent';
変数であるcountと状態を変更する関数であるsetCountの2つを受け取ります。
これで子コンポーネントでもcountとsetCountを使った状態管理ができるようになります。
const { count, setCount } = useContext(CountContext);
まとめるとこのようになります。
import React, { useContext } from 'react';
import { CountContext } from './ParentComponent';
export const ChildComponentC = () => {
// 親コンポーネントで設定した値を受け取る
const{ count, setCount } = useContext(CountContext);
return (
<div>
<p>カウント: {count}</p>
<button onClick={() => setCount(count + 1)}>+</button>
<button onClick={() => setCount(count - 1)}>-</button>
</div>
)
}
子コンポーネントでsetCountを使っても、親コンポーネントでsetCountを使っても、同じようにcountに反映させることができます。
stateの管理も簡単にできるんだね!
汎用的に使う方法
コンポーネントの中でcontextを作成して利用していましたが、context自体を別のコンポーネントとして切り出して使う方法です。
別のコンポーネントとすることで汎用的にcontextを使えるようになります。
汎用的なcontextコンポーネント、親コンポーネント、子コンポーネントの3つをそれぞれ解説していきます。
汎用名的に使うcontextコンポーネント
まずはcreateContext
とuseContext
をインポートします。
このcontext内でstateも管理したいのでuseState
もインポートしておきます。
import React, { createContext, useContext, useState } from 'react';
context用のコンポーネントなのでcreateContext
でcontextオブジェクトを作成します。
const CountContext = createContext();
作成したstateをProviderのvalueに指定します。children
をProviderで囲み、childrenの内容を返すようにします。
const [count, setCount] = useState(0);
<CountContext.Provider value={{ count, setCount }}>
{children}
</CountContext.Provider>
children
は特別な意味を持つ名前です。
childrenと記述することで、自身のコンポーネントが呼び出されたとき、呼び出し元のタグの中で記述された内容がchildrenの中に渡ってきます。
まとめるとこのようになります。
import React, { createContext, useContext, useState } from 'react';
const CountContext = createContext();
export const CountProvider = ({ children }) => {
const [count, setCount] = useState(0);
return (
<CountContext.Provider value={{ count, setCount }}>
{children}
</CountContext.Provider>
);
}
親コンポーネント
context用のコンポーネントをインポートします。
CountProviderをインポートしているのでcontext用の機能は親コンポーネントでインポートする必要がなくなります。
import React from 'react';
import { CountProvider } from './providers/CountProvider';
インポートしたCountProviderで子コンポーネントを囲います。
<CountProvider>
<ChildComponentC />
</CountProvider>
これはCountProviderで囲まれているので以下のようなイメージの記述になっています。
<CountContext.Provider value={{ count, setCount }}>
<ChildComponentC />
</CountContext.Provider>
まとめるとこのようになります。
import React from 'react';
import { CountProvider } from './providers/CountProvider';
export const ParentComponent = () => {
return (
<div>
<CountProvider>
<ChildComponentC />
</CountProvider>
</div>
);
}
子コンポーネント
親コンポーネントではなくcontext用のコンポーネントからcontextをインポートします。
import React, { useContext } from 'react';
import { CountContext } from './providers/CountProvider'';
まとめるとこのようになります。
import React, { useContext } from 'react';
import { CountContext } from './providers/CountProvider'';
export const ChildComponentC = () => {
// context用コンポーネントで設定した値を受け取る
const{ count, setCount } = useContext(CountContext);
return (
<div>
<p>カウント: {count}</p>
<button onClick={() => setCount(count + 1)}>+</button>
<button onClick={() => setCount(count - 1)}>-</button>
</div>
)
}
context用のコンポーネントを分けることで、
より管理がしやすくなった感じがする!
まとめ
少し独特な記述も出てきたけど、
useContextの使い方について解説したよ!
- useContextはデータの共有を行うときに使うフック
- データの共有元はcreateContextを使う
- 作成したcontextオブジェクトを使って〇〇.Providerとして、データを共有したいコンポーネントを囲む
- 共有したいデータはProviderのvalueに指定する
- データの共有先ではuseContextを使う
データの共有が便利にできることが分かったよ!
使ってみる!