在庫・出荷管理アプリを作ってます⑤:React初心者がコンポーネント化してみたけど・・・なんか違う気が。

前回、流通業者の出荷予定登録機能を実装しました。
その際に「コンポーネント化を積極的に行った」と書きましたが、実際にやってみて感じた理想と現実のギャップについて、リアルな体験談を書いてみます。

目次

最初の理想:「コンポーネント化すれば使い回せる」

React学習時の思い込み

React を学習した時、以下のような「教科書的な知識」を身につけました:

  • コンポーネント化すると再利用できる
  • DRY原則(Don’t Repeat Yourself)を守るべき
  • 責務を分離して保守性を向上させる

そこで、最初に作った FlexibleShipmentTable コンポーネントを④⑤⑥⑦の全機能で使い回そうと考えました。

理想的な構想

FlexibleShipmentTable
├── ③出荷予定登録 (planned-shipments)
├── ④生産者の出荷確認 (shipment-view)
├── ⑤生産者の伝票作成 (new-shipment)
├── ⑥OCR登録 (new-shipment)
└── ⑦出荷履歴確認 (shipments)

「1つのコンポーネントで全部カバーできる!」と思っていました。

現実:用途が違うとUIも違う

実際にできた構成

結果的に、以下の11個のコンポーネントに分かれました:

/auth/new-shipment/page.tsx
├── NewShipmentForm.tsx
├── DestinationSelect.tsx
└── OcrUpload.tsx

/auth/planned-shipments/page.tsx
├── FlexibleShipmentTable.tsx (PC用)
├── ShipmentRow.tsx
└── MobileFlexibleShipmentTable.tsx (スマホ用)

/auth/shipment-view/page.tsx
└── MobileShipmentView.tsx

/auth/destinations/page.tsx
├── DestinationForm.tsx
└── DestinationTable.tsx

/auth/shipments/page.tsx
└── CompletedShipmentTable.tsx

/auth/shipment-trader/page.tsx
└── CompletedShipmentTable.tsx (再利用予定)

なぜこうなったか

用途が違うと、必要なUIも違うことが分かりました:

  • 商社の入力画面 vs 農家の確認画面
  • PC表形式 vs スマホ縦並び
  • 登録用 vs 表示専用
  • 編集可能 vs 読み取り専用

例えば:

  • 商社は複数行を一括入力したい → 表形式
  • 農家は当日分だけ確認したい → シンプルな一覧
  • スマホは画面が狭い → 縦並び表示

ChatGPTとの格闘

「コンポーネントを分けないといけない」論争

開発中、ChatGPTに「全部1つのコンポーネントで済ませたい」と相談しました。

:「FlexibleShipmentTable 1つで全部できないの?」

ChatGPT:「コンポーネントは責務を分離すべきです。以下の理由で分けることをお勧めします:

  • 登録と表示では責務が異なる
  • PC とモバイルでは UI 構造が異なる
  • 将来的な拡張性を考えると…」

結局、ChatGPTの言う通りに分けました。

実際に分けた結果

メリット

  • 各コンポーネントの責務が明確
  • 修正時に影響範囲が特定しやすい
  • テストしやすい

デメリット

  • ファイルが増えて把握が大変(11個のコンポーネント)
  • どこに何が書いてあるか分からない
  • 修正時に複数ファイルを行き来する必要がある

別のアプローチ:「3回出てきたらコンポーネント化」

後日、Claude に相談したところ、こんなアドバイスをもらいました:

Claude:「実際に同じような処理が3回出てきたらコンポーネント化を検討してみては?最初はベタ書きで作って、重複が発生してから共通化する方法もあります。」

これを最初に聞いていたら、違うアプローチを取っていたかもしれません:

  1. 最初はベタ書きで各画面を作成
  2. 重複が3回発生したらコンポーネント化を検討
  3. **「使い回し」より「ファイルが長すぎて辛い」**時に分割

振り返り:結局どうだったか

実際に使い回せたもの

11個のコンポーネントのうち、実際に使い回せたのは:

  • ShipmentRow.tsx – 表の1行部分
  • DestinationSelect.tsx – 出荷先選択プルダウン
  • CompletedShipmentTable.tsx – 出荷履歴表示(予定)

3個だけでした。

「ベタ書きでも良かった」説

正直に言うと、**「ベタ書きの方でも良かった」**と思います。

理由

  • 規模的にはそこまで複雑ではない
  • 使い回しは結局あまりなかった
  • 1ファイルで完結する方が楽だった
  • 開発スピードはベタ書きの方が速かった

でも、コンポーネント化して得られたもの

一方で、以下のメリットもありました:

  • 責務が明確になった
  • 修正箇所が特定しやすい(OcrUpload だけいじれば OK)
  • テストしやすい(各コンポーネント単体で)
  • なんとなく「ちゃんとした」感

現実的な結論

「どちらでも良かった」が正解

完全に間違いでも、完全に正解でもない。

「まあ、どっちでも動くよね」

これが、実際の開発でよくある選択だと思います。

今後の方針

結局、**「もう作ったから、作り直さない」**です。

動いているものを作り直す意味はありません。

コンポーネント化したことで修正時には恩恵を受けられそうなので、とりあえずはこのまま継続します。

やってみてわかったこと

理論より実践

教科書通りにやっても、実際の開発では思った通りにならないことが多いです。

でも、やってみてわかることも沢山あったので、それはそれで良い経験だったと思います。

学んだこと

1. コンポーネント化のタイミング

  • 最初から完璧を目指さない
  • 重複が発生してから検討する
  • 「使い回し」より「責務分離」を重視する

2. 「教科書通り」が正解とは限らない

  • 理論と実践にはギャップがある
  • 規模や要件によって最適解は変わる
  • 「どちらでも動く」なら、どちらでも OK

3. 開発は完璧である必要はない

  • 動いているならそれで良い
  • 後から改善すれば良い
  • 完璧を目指して進まないより、動くものを作る方が大事

次回の開発では…

今度同じような機能を作る時は:

  1. 最初はベタ書きで作る
  2. 本当に使い回す場面が出てきたらコンポーネント化
  3. **「ファイルが長すぎて辛い」**と感じたら分割

このアプローチを試してみたいと思います。

まとめ

「React初心者がコンポーネント化してみた結果」

  • 理想:1つのコンポーネントで全部カバー
  • 現実:11個のコンポーネントに分散
  • 結論:「ベタ書きでも良かった」けど、「これはこれで OK」

完璧な設計なんて最初から分からないし、作りながら調整していくのが普通の開発プロセスだと思います。

目次