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