1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Reactを基本からまとめてみた【18】【React Hook (useContext) ③】

Last updated at Posted at 2021-11-30

useContextはどういう時に使用するか

コンポーネントをまたいで値を渡す時。

propsで渡すと孫コンポーネントに渡す時に、一度、子や孫コンポーネントを経由しなければならなくなりバケツリレーになる。(propドリル)

さらにContextのいい点はContextで管理している状態や関数をそれぞれの子コンポーネントで共通して扱えるということ。

image.png

Contextの概念図

以下の図は、AuthContextという認証関連の変数や操作ロジックを扱ったContextと、それを実際に使用する2つのコンポーネントとの関係性を図示したもの。

image.png

・ログインしているかどうかを示す変数であるisAuthがAuthContextで一元的に管理されている
・この子コンポーネントはisAuthを使えるようになり、isAuthの値に応じた処理を書くことができるようになる
・コンポーネントAではloginHandlerを呼び出すことで、AuthContext内のisAuthをtrueに変更することができる

Contextの使い方

今回はこういうファイル構成にしてComponentAとComponentBでそれぞれ共通の変数を扱うようにする。
実際にはありえないがまぁ今回はよしとする。

├── App.jsx
├── AuthContext.jsx
├── ComponentA.jsx
└── ComponentB.jsx

Step 1.Contextの作成

まずは子コンポーネントで使う変数や関数を管理するためのContextを作成する。
ここではAuthContextを作成する。

ポイントは以下の2つ

①createContextでContextオブジェクトを作成し、外部で使えるようにexportする
②子コンポーネントをContextオブジェクトのProviderでラップすることでvalueに記載した変数や関数を子コンポーネントで使用できるようにする

AuthContext.jsx
import React, { useState, createContext } from 'react';

// Contextオブジェクトを作成し、exportする
export const AuthContext = createContext();

const AuthContextProvider = props => {
  const [isAuth, setIsAuth] = useState(false);

  const login = () => {
    setIsAuth(true);
  }

  return (
    // Providerで子コンポーネントをラップする
    // valueに子コンポーネントで使いたい変数や関数を与える
    <AuthContext.Provider value={{login, isAuth}}>
      {props.children}
    </AuthContext.Provider>
  )
}

export default AuthContextProvider;

createContext は Contextオブジェクトを作り出していて、これによって Provider とConsumer ができる。
Provider は与える側、Consumer は受け取る側。
hooks ではConsumer は useContext で代用される。

Step 2.Providerを適切な位置に配置する

App.jsx
import { ComponentA } from "./ComponentA";
import { ComponentB } from "./ComponentB";
import AuthContextProvider from "./AuthContext";

function App() {
  return (
    <BrowserRouter>
      <AuthContextProvider>
        <Switch>
          <Route path="/a" component={ComponentA} />
          <Route path="/b" component={ComponentB} />
        </Switch>
      </AuthContextProvider>
    </BrowserRouter>
  );
}

export default App;

子コンポーネントであるComponentAとComponentBではStep1のAuthContextProviderで定義した変数と関数を使える準備ができたということになる。

Step 3.子コンポーネントでContextを使う

ComponentA

①useContextをimoprt
②useContextの引数にAuthContextで作成したContextオブジェクト(Step 1で作成)を入れる
③使いたいオブジェクトを取り出す(ここではisAuthとlogin)

ComponentA.jsx
import React, { useContext } from "react";
import { AuthContext } from "./AuthContext";
import { Link } from "react-router-dom";

const ComponentA = () => {
  const { isAuth, login } = useContext(AuthContext);

  return (
    <div className="auth">
      <h2>ComponentA</h2>
      {isAuth ? (
        <h2>認証されました</h2>
      ) : (
        <>
          <h2>認証されてません</h2>
          <button onClick={login}>ログイン</button>
        </>
      )}
      <Link to="/b">ComponentBへ</Link>
    </div>
  );
};

export default ComponentA;

ここではisAuthの真偽によって表示する内容を変えている。
さらにonClickイベントでログイン関数を呼び出している。

ComponentB

ComponentB.jsx
import React, { useContext } from "react";
import { AuthContext } from "./AuthContext";

const ComponentB = () => {
  const { isAuth } = useContext(AuthContext);

  return (
    <div>
      <h2>ComponentB</h2>
      {isAuth ? <h2>認証されました</h2> : <h2>認証されてません</h2>}
      <Link to="/a">ComponentAへ</Link>
    </div>
  );
};

export default ComponentB;

ComponentBも同様にisAuthを取り出して表示内容を変えている。

Contextによって何ができるようになったのか

①ComponentAでログインボタンを押すことでlogin関数が呼び出される
②AuthContextのisAuthがfalseからtrueに変更される
③ComponentA, ComponentBでそれぞれ変更されたisAuthの値を使えるようになった

つまりComponentAによる値の変更をComponentBで検知できるようになった。

参考サイト

[useContextの使い方]
(https://www.sunapro.com/usecontext/)

1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?