【React/Next.js】「propsはコンポーネントの設計書」とは?propsの渡し方
今日は現場の相互レビューで指摘された「propsはコンポーネントの設計書」という言葉について調べて、propsの渡し方について考えていこうと思う。
実際に指摘を受けたコード
type Pict = {
export type PictCardProps = {
pictNo?: string
filename?: string
}
const picts: Pict[] = [
{
pictNo: 1,
filename: "test1.png",
},
{
pictNo: 2,
filename: "test2.png",
},
{
pictNo: 3,
filename: "test3.png",
},
{picts.map((pict) => (
<PictCard
pictNo={pict.pictNo}
filename={pict.filename}
/>
))}
上記のコードはPictCardコンポーネントにpropsを渡している。
渡すpropsの型は string|unedefined
なので
これを受け取ろうとすると
type PictCardProps = {
pictNo?: string
filename?: string
}
export const PictCard = ({
pictNo,
filename,
}: PictCardProps) => {
return (
<div>
<div>
<div>
<Image
id={pictNo ?? ""}
src={filename ?? ""}
alt={pictNo ?? ""}
/>
</div>
<div>
<h3>{filename }</h3>
<p>pictcardです</p>
</div>
</div>
</div>
上記のようにstring|unedefined
をそのまま受け取り、受け取り側で使う場合
毎回 hogehoge ?? ""
をつけることになる。
propsは渡す側で整えておく
今回指摘された内容は要するにpropsは渡す側で整えておくということだろう。
確かに受け取り側で使うたびにundefinedの場合を演算子で書くのはかなり不便な気もする。
受け取り先でもオプショナルで処理が変わる場合は別だけど。
では具体的にさっきのコードをどう書けばいいかっていうと
type Pict = {
export type PictCardProps = {
pictNo?: string
filename?: string
}
const picts: Pict[] = [
{
pictNo: 1,
filename: "test1.png",
},
{
pictNo: 2,
filename: "test2.png",
},
{
pictNo: 3,
filename: "test3.png",
},
{picts.map((pict) => (
<PictCard
// ここですでにundefinedの場合の渡す内容を書いておく
pictNo={pict.pictNo ?? ""}
filename={pict.filename ?? ""}
/>
))}
type PictCardProps = {
// undefinedの場合の内容は定義してあるのでオプショナルを消す
pictNo: string
filename: string
}
export const PictCard = ({
pictNo,
filename,
}: PictCardProps) => {
return (
<div>
<div>
<div>
<Image
// そのまま使える
pictNo={pictNo}
src={filename}
alt={pictNo}
/>
</div>
<div>
<h3>{filename }</h3>
<p>pictcardです</p>
</div>
</div>
</div>
こう書くことでコードの可読性も上がる。
コンポーネントの受け取りPropsの型を見ることで、
このコンポーネントでは文字列だけで使われているのか、undefinedの場合に他の処理を返すようにしているのか等一目瞭然ということから
「propsはコンポーネントの設計書」という記事があったのだろう。
あとがき
フロントエンドエンジニアとして現場に配属されて3ヶ月。
こういう指摘がある時に、個人開発が全然役に立たないことを実感する。
チーム開発である以上、コードの可読性はとても重要だし可読性を考えて実装するのは未経験ではなかなか出来ないことなので
未経験は門前払いされるのかな、と思ったり。
SESあるあるの「経験3年」という肩書きを背負っているので、こういう時にボロが出るし
きっと「3年でこれってなかなかポンコツ」と思われているに違いない。笑
それでも未経験の自分を拾ってくれた自社には感謝しかないけれど。
この記事が新人さんや未経験の目に止まって、初心者脱却の1つになれば幸いです😭
Discussion
失礼します、差し出がましいアドバイスで恐縮ですが、
仕様によってどのような Props にするのが最善かは変わってくるので、臨機応変に考えるほうが良いと思います。
《PictCardについての仕様》と、《使用する側(API から取得したデータをPictCardに渡す側)のコード》を分離して考えて、以下が僕の意見です。
filename: string | undefined
にするfilename?: string
だと、使用側での渡し忘れの原因になるので、https://typescriptbook.jp/reference/tsconfig/exactoptionalpropertytypes を有効にして、このような場合には避けたほうが安全。もしくは、zod, valibot のようなライブラリを使って、バックエンドから受け取ったデータを予め厳しく検証しておくことも可能です。
コメントありがとうございます。
ご指摘の通り臨機応変に対応していくことも、keyに関しても存じ上げております。
この記事は、現場で言われたことを自分なりにまとめておきたかったのでコピペしたのですが
現場コードをまるっと写す訳にはいかないと思い、雑に書いてしまったところがあります、
育児となれない現場とで中々時間が取れない中
書く時間があまりにも無いため自分が分かればいいと思い読者さんのことを考えられておりませんでした、、
(非公開にしないのにも諸々理由があるので申し訳ないです。)
知識も経験の浅い私が中途半端に書いてしまった私の記事を読んだ方が誤解すると良くないので
今後は前書きやあとがき等に注意書きしようかと思います。
ご指摘ありがとうございました。
いえいえ、こちらこそ記事だけ見てお節介なコメントをしてしまい、申し訳ないです💦
確かに、現場で学んだことをアウトプットするのは、うまく抽象化しないといけないので負担がすごいですよね...
大変な中とは思いますが、応援させていただきます