こんにちは!Reactの学習、楽しく進めていますか?
画面をパーツごとに分けて組み立てられるようになってくると、「おっ、なんだかすごいアプリを作っているぞ!」というワクワク感が出てきますよね。
でも、そんな学習の途中で、多くの人が「うわっ…」とつまずく瞬間があります。それが、「Props(プロプス)の受け渡しと、その型付け」です。特に、親から子へデータを一括でバトンタッチする便利技「スプレッド演算子(`…props`)」を使おうとしたとき、TypeScriptの赤い波線(エラー)に怒られて途方に暮れてしまった経験はありませんか?
「全部まとめて渡したいだけなのに、なんでこんなに怒られるの……」
大丈夫ですよ!安心してください。今日は、このスプレッド演算子と型安全性の関係を、身近な例えを交えながら、一緒にやさしく解きほぐしていきましょう。
—
1. スプレッド演算子ってなぁに?(宅配便の「おまかせ段ボール」の例え)
Reactでは、親コンポーネントから子コンポーネントへ、データや設定を「Props」というお盆に載せて渡します。
例えば、ボタンを作る componente(コンポーネント)を考えてみましょう。ボタンには、文字(`label`)だけでなく、クリックされたときの処理(`onClick`)、さらにHTML本来が持っている属性(`disabled`や`type`など)もたくさん渡したいことがありますよね。
ひとつひとつ手渡ししていくと、コードがこんな風にパンパンになってしまいます。
// ひとつずつ手渡しする例(ちょっと大変…)
「あーー、めんどくさい!全部まとめてダンボールに詰めて、パッと送りつけたい!」
そんなときに使うのが、スプレッド演算子(`…`)です。
// スプレッド演算子で一括ポン!と渡す例
const buttonProps = {
label: “送信”,
onClick: handleClick,
disabled: isSending,
type: “submit”,
className: “btn-primary”,
};
return
この `…buttonProps` は、まるで「中身をぜーんぶバラして、宛先のコンポーネントに平らに並べて配置してね!」という魔法の呪文です。とってもスマートで、コードがスッキリしますよね。
—
2. でも、TypeScriptという「厳しい警備員」がやってくる
このスプレッド演算子は最高に便利なのですが、ここでTypeScriptという頼もしくも厳しい警備員が登場します。
「ちょっと待った!その段ボールの中に、何が入っているか証明書を見せてください!」
TypeScriptは、「どんなデータが来てもいいよ」という雑な状態を嫌います。「このPropsには、この型(種類)のものしか入れちゃダメ!」と厳しくチェックするのです。ここをサボると、後で「あれ?存在しないプロパティを読もうとしてアプリが真っ白になった!」というバグの原因になってしまいます。
—
3. 型安全を守りながらスプレッド渡す実践コード
では、どうすればこの「便利さ」と「型安全(エラーのない安心感)」を両立できるのでしょうか?
実際に、よくある「カスタムボタン」のコードを見てみましょう。
import React from ‘react’;
// ① 子コンポーネントが受け取るPropsの「設計図(型)」を作ります
// HTMLの標準的なボタンプラス、独自の「label」を受け取れるようにします
type MyButtonProps = React.ButtonHTMLAttributes
label: string;
};
// ② 子コンポーネントの定義
// 受け取ったたくさんのPropsを「…rest」という名前のリュックサックにまとめて入れます
export const MyButton: React.FC
return (
// リュックサック(rest)を、そのまま本物の
コードのポイント解説
- `React.ButtonHTMLAttributes
` : これが魔法の合言葉です。「普通のHTMLのボタンが持っている属性(`disabled`, `onClick`, `type`, `id` などなど)をぜんぶ丸ごと借用します!」という意味になります。 - `&`(交差型): 「HTMLのボタンの属性」に、私たちが独自に作りたい「`label: string`」をドッキングさせる合体パーツです。
- `{ label, …rest }`: 届いた荷物から `label` だけを取り出し、残りの大量の属性(おまけの機能たち)を `rest` という名前の箱にひとまとめにしています。この命名は `props` でも構いませんが、`rest`(残りのもの、という意味)にしておくと、「あ、これは一括で流し込む用の残りカスだな」と一目でわかるので現場で好まれます。
—
4. やってはいけない!不要なPropsの混入を防ぐ注意点
ここで、実務でやりがちな「うっかりミス」についてお話しします。
スプレッド演算子は便利すぎるあまり、「本当は渡したくない余計なデータまで、子孫にズボラに流し込んでしまう」という副作用があります。
例えば、親コンポーネントで使っていた「ユーザーのパスワード情報」や「秘密のフラグ」が、うっかり `…props` の中に混ざっていたとしましょう。それがそのまま末端の `` タグや `
最悪の場合、ブラウザのDOM要素に変な属性が露出してしまい、セキュリティ上のリスクや予期せぬレイアウト崩れを引き起こします。
対策:使う分だけきっちり「分割代入」で避ける
親から受け取ったすべてのPropsをそのまま横流しするのではなく、「不要なものは手元でキャッチして捨てる(あるいは使わない)」という一手間が、プロの技の見せどころです。
type CardProps = {
title: string;
secretCode: string; // これは内部だけで使いたい秘密のデータ!
[key: string]: any; // その他のHTML属性を受け入れる場合(なるべく避けたいですが…)
};
export const SafeCard = ({ title, secretCode, …htmlAttributes }: CardProps) => {
// secretCode はこの中でこっそり使うだけで、HTMLには絶対にばら撒かない!
console.log(“秘密のコードで何か処理するよ:”, secretCode);
return (
{title}
{/ 画面には secretCode は一切露出しない!安全安心! /}
);
};
—
5. まとめ:怖がらなくて大丈夫、一歩ずつ進めよう
スプレッド演算子によるPropsの展開は、慣れるまでは「何がどこに流れているのか見えにくい」と感じて怖くなるかもしれません。
でも、以下の2つさえおさえておけばもうバッチリです!
1. 型(設計図)をしっかり書く(`React.HTMLAttributes`などを活用して車輪の再発明をしない)
2. 渡すものと、隠すものを意識する(不要なデータが外に漏れ出さないように、分割代入でコントロールする)
最初から完璧にやろうとしなくて大丈夫です。エラーが出たらTypeScriptくんが「ここが違うよ!」と優しく(時には厳しく)教えてくれますので、その都度訂正しながら自分の引き出しを増やしていきましょう。
あなたのReact開発が、少しでも快適で楽しいものになりますように。
それでは、また次の記事でお会いしましょう!

コメント