propsのバケツリレー
値は必ず一段ずつ降りる
props は親から子へ、一段ずつしか渡せません。孫やひ孫へ一気に届ける近道はありません。
App owner を持っている
└─ WorkSection
└─ WorkList
└─ WorkCard owner を表示したいApp が持っている値を WorkCard で使いたいとき、途中の WorkSection と WorkList も受け取って下へ渡す必要があります。自分では使わないのに、です。
この形を props のバケツリレー、英語では props drilling と呼びます。バケツを手渡しで運ぶように、途中の人が全員手を出さないと水が届かない、という様子から来ています。
実際に書くとこうなる
function WorkSection({ owner }) {
return <WorkList owner={owner} />;
}
function WorkList({ owner }) {
return (
<ul className="work-list">
{works.map((work) => (
<li key={work.id}>
<WorkCard owner={owner} title={work.title} />
</li>
))}
</ul>
);
}WorkSection の中に owner という文字は2回出てきますが、この部品は owner を1ミリも使っていません。受け取って、そのまま渡しているだけです。
何が困るのか
2階層くらいなら、むしろ分かりやすい仕組みです。値がどこから来たかを追うとき、上へたどれば必ず出どころに着きます。困るのは深くなってからです。
- 渡す値を1つ足すたびに、途中の部品を全部書き直すことになる
- 途中の部品の props が、自分に関係ない項目でふくらむ
- 途中の1か所で渡し忘れると、いちばん下だけが静かに空になる。エラーは出ない
3つめが特にやっかいです。画面に何も出ないだけなので、どの階層で落としたのかを上から順に探すことになります。
逃げ道はあるが、まだ使わない
React には、この手渡しを飛ばして深いところへ値を届ける Context という仕組みがあります。ログイン中のユーザーやテーマの色など、画面のあちこちで使う値に向いています。ただし Context は「どこから来た値か」が読みづらくなる側面もあり、浅いバケツリレーを無理に置き換えると、かえって追えないコードになります。
だから入門のいまは、まず手渡しの形を体に入れます。Context は React 実践で扱います。手渡しが面倒だと感じた経験があるかどうかで、Context を学ぶときの理解の深さが変わります。
つまずきどころ
途中で名前を変えて渡してしまう間違いが多いです。<WorkList user={owner} /> と書いてしまうと、受け取る側は user で取り出さなければなりません。渡す名前と受け取る名前は必ず一致させます。
演習
途中の階層で止まっているバケツを、いちばん下まで届けます。