LoginSignup
161
91

More than 3 years have passed since last update.

useContextのしくみ

Last updated at Posted at 2018-12-19

Dave Ceddia氏による全5回におよぶReact Hooks入門記事の第5回を本人の許可を得て意訳しました。
誤りやより良い表現などがあればご指摘頂けると助かります。

原文: https://daveceddia.com/usecontext-hook/


すべての新しいReact Hooksの中で議論中のテーマがあります。ほとんど全てが、ファンクションコンポーネントをクラスコンポーネント同等にするために存在しています。

useContext フックは少し違っています。仕事をよりラクにしてくれるだけのものです。

ReactのContext APIを知らない方のために補足しておきますと、アプリケーション内深くまでデータを渡す方法、それも手動で複数階層にまたがってバケツリレーをせずに済む方法です。データを引き回すことさえできれば良いという時には、Reduxのようなツールの代替手段として機能します。Contextについて学び、Reduxとの違いを知るにはこちらへどうぞ。

この記事では、 useContext がどのようにContextを扱いやすくするのかを見ていきます。

メモ:Hooksは現在α版であり、プロダクション環境ではまだ使用できません。APIはさらに変更される可能性があるため、現時点ではプロダクションアプリの書き換えはオススメしません。Open RFCにコメントし、公式ドキュメントFAQにも目を通してください。

従来の一般的な方法

典型的なContext APIの使用例はこのような感じです。

import React from "react";
import ReactDOM from "react-dom";

// Contextを生成する
const NumberContext = React.createContext();
// 2つの値を持つオブジェクトを返す
// { Provider, Consumer }

function App() {
  // Providerを活用して値を全ての
  // 子要素と孫要素に利用可能にする
  return (
    <NumberContext.Provider value={42}>
      <div>
        <Display />
      </div>
    </NumberContext.Provider>
  );
}

function Display() {
  // Consumerを活用してcontextから取得した値を使う
  // このコンポーネントはpropsを取らないことに注意!
  return (
    <NumberContext.Consumer>
      {value => <div>The answer is {value}.</div>}
    </NumberContext.Consumer>
  );
}

ReactDOM.render(<App />, document.querySelector("#root"));

Context APIについて詳しくはこちらで触れています。

useContextを使ったモダンな方法

DisplayuseContext フックを使ってリファクタして、どのような感じになるか見てみましょう。

// useContextをimportする(もしくはReact.useContextを使う)
import React, { useContext } from 'react';

// ...

function Display() {
  const value = useContext(NumberContext);
  return <div>The answer is {value}.</div>;
}

これだけです。 useContext を呼び、 React.createContext から取得できるcontextオブジェクトを渡すと、値が利用可能になります。見やすくなったでしょう?

注目すべき唯一のポイントは、contextオブジェクトを丸ごと useContext に渡さなければならないということです。consumerだけではダメです!もし忘れるとReactが警告してくれますが、忘れないでくださいね?

ネストされたConsumer

コンポーネントが複数の親contextからデータを受け取りたいような場合はこうなります。

function HeaderBar() {
  return (
    <CurrentUser.Consumer>
      {user =>
        <Notifications.Consumer>
          {notifications =>
            <header>
              Welcome back, {user.name}!
              You have {notifications.length} notifications.
            </header>
          }
      }
    </CurrentUser.Consumer>
  );
}

たった2つの値を受け取るのにひどいネストになってしまいます。 useContext を使って良い感じにしてみましょう。

function HeaderBar() {
  const user = useContext(CurrentUser);
  const notifications = useContext(Notifications);

  return (
    <header>
      Welcome back, {user.name}!
      You have {notifications.length} notifications.
    </header>
  );
}

ずっと読みやすくなりましたね。

広がるHooksの世界

今週カバーした以外にも多くのHooksがあります。メモ作成のための useMemo のような素晴らしいものありますので、ぜひ公式のHooks APIドキュメントで学んでみてください。公式ドキュメントも素晴らしいですが、Hooks入門から始めることをおすすめします。

Hooksウィークに投稿した私の他の記事も再掲します。

毎週記事を投稿しています(ビデオもたまに)。もっと情報が必要であれば、ボックスにメールアドレスを登録してください。

161
91
2

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
161
91