useContextで使う
箱から取り出す
前の回で作った ThemeContext は、まだ誰も覗いていません。覗くのが useContext です。
表示言語の Context を読む部品なら、次のように書けます。
TypeScript (JSX)
function HelpLink() {
const language = useContext(LanguageContext);
const label = language === "ja" ? "ヘルプ" : "Help";
return <a href="/help">{label}</a>;
}useContext(ThemeContext) は、自分より上にあるいちばん近い Provider の value を返します。PriceTag が何段深くても、間に何があっても関係ありません。props を1つも受け取らずに theme が手に入ります。
戻り値の型は、箱を作るときに書いた <Theme> から決まります。Theme の値を number 型の変数に入れるような取り違えは、型検査で見つけられます。
バケツリレーを消す
取り出せるようになったので、途中の受け渡しは要らなくなります。
ItemListPropsから theme を消すItemCardPropsから theme を消す- 呼び出しの
theme={theme}を消す
ItemList と ItemCard が、商品を並べるという本来の仕事だけを持つ形に戻ります。使う人が直接取りに行くので、通り道になる部品がいなくなるわけです。
Provider が無いとどうなるか
useContext は、上に Provider が見つからないと既定値を返します。作るときに書いた "light" です。
エラーにならないので気付きにくいのが厄介なところです。「切り替えても何も変わらない」という不具合の多くは、Provider の外側で useContext を呼んでいるのが原因です。既定値は、そういうときの目印になる値にしておくと助かります。
使いどころ
Context は便利ですが、何でも入れる置き場ではありません。テーマ、ログイン中のユーザー、言語のように、アプリのあちこちで同じものを見たい少数のものに向いています。1つの画面の中だけで使う値は、これまでどおり props で足ります。
演習
PriceTag が useContext でテーマを取り、途中の受け渡しを消します。