LoginSignup
0
0

More than 1 year has passed since last update.

React開発Part6~Context~

Posted at

はじめに

 こんにちは、Tunです。
今回は、Stateの管理について深堀していきたいと思います。

stateの管理問題

 Reactにおいて、コンポーネントの構成が5階層の場合、一番上の階層のコンポーネントで定義しているstateを一番下の階層のコンポーネントに渡したい場合は、propsで渡すことができます。
 しかし、この方法では問題点が多く、バケツリレーのように複数のコンポーネントにまたがってstateの受け渡しが行われ、コードの複雑化や、再利用不可のコンポーネント、中間コンポーネントにおける無駄なpropsの受け取り、さらには一番下の階層のコンポーネントにstateを渡そうとすると、全てのコンポーネントが再レンダリングされるというデメリットがあります。
 この、無駄なコードや挙動を減らすためにstateの管理方法を考えなければならないというわけです。

Global stateの管理方法
:point_right:useContext以外にもReduxやRecoil、Apollo Clientなどがありますが、今回はContextの解説のみで、別の記事で他の管理方法を書きたいと思います。

Context

 上記のstateの管理問題を解決してくれるオーソドックスな方法は、Reactが提供しているContextを使うことです。

  1. React.createContextContextの器を作成する
  2. 作成したContextProviderでGlobal stateを扱いたいコンポーネントを囲む
  3. stateを参照したいコンポーネントでReact.useContextを使う

 上記の手順で、GlobalなState管理が可能になります。
詳しく解説:point_down:

1. まずはContextを保持するためのプロバイダーコンポーネントをExampleProvider.jsxという名前で、providersというフォルダの配下に作成します。

ExampleProvider.jsx
import { createContext } from "react";

export const ExampleContext = createContext({});

 これでContextの器の作成が完了しました。createContextの引数にはデフォルト値が設定でき、上記の例は空のオブジェクトが初期値になっています。

2. Contextの器を作成しただけでは使えるようにはなりません。ProviderでContextの値を参照したいコンポーネント群を囲む必要があります。

ExampleProvider.jsx
import { createContext } from "react";

export const ExampleContext = createContext({});

export const ExampleProvider = props => {
 const {children} = props;

 //動作確認のためのオブジェクト
 const sampleObj = { sampleObj : "test" };

 //ExampleContextの中にProviderがあるのでそれでchildrenを囲む
 //valueにはグローバルに扱う実際の値を設定する
 return ( 
  <ExampleContext.Provider value={sampleObj}>
   {children}
  </ExampleContext.Provider>
 );
};

Providerコンポーネントはなんでも囲めるようにPropsとしてchildrenを受け取るようにするのがポイントです。このProviderというコンポーネントにはvalueというPropsを設定することができ、ここにグローバルに管理する実際の値を設定します。

index.js
import ReactDOM from "react-dom";

import { App } from "./App";
import { ExampleProvider } from "./components/providers/ExampleProvider";

ReactDOM.render(
 <ExampleProvider>
  <App />
 </ExampleProvider>,
 documenet.getElementById("root")
);

 これで、Provider周りの準備が整いました。

3.実際にContextの値を参照してみましょう。

ExampleUseContext.jsx
import { useContext } from "react";

import { ExampleContext } from "./components/providers/ExampleProvider";

const contextValue = useContext(ExampleContext);
console.log(contextValue); //{sampleValue : "test"}

 まず、ReactからuseContextimportし、作成したExampleContextもimportします。importしたuseContextの引数に参照するContextの値を指定します。
 このようにContextの値を使用するコンポーネント側では、useContextを使いその引数に対象のContextを指定するだけで参照できます。

再レンダリングに注意
:point_right:Contextオブジェクトの値が何か更新されたときは、useContextでそのContextを参照しているコンポーネントは全て再レンダリングされます!
 なので、1つのContextに属性の異なるいろんなStateを詰め込むのは避けましょう。

 次回はTypeScriptに軽く触れたいと思います:wave:

参照

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0