コンポーネント、ステート、コンポジション、TypeScript、そしてReactのエコシステムについて見ていきます。
Reactが現代的なWebアプリケーション開発に向いている大きな理由のひとつは、UIを小さく、再利用しやすいコンポーネントとして構築できる点にあります。 WebサイトやWebアプリケーションは、見た目だけで考えると、ひとつの大きな画面のように見えます。しかし、実際に開発する側から見ると、その画面は多くの部品の集合体です。 ヘッダー、ナビゲーション、ボタン、カード、フォーム、モーダル、リスト、画像、セクション、フッター。さらにブログであれば、記事カード、タグ、投稿日、サムネイル、本文エリア、関連記事、ページネーションなど、細かなUI要素がたくさん存在します。 Reactでは、こうしたUIの一つひとつをコンポーネントとして分けて考えることができます。 たとえば、ブログ記事を表示するカードであれば、BlogPostCard のようなコンポーネントとして切り出せます。その中にタイトル、概要、タグ、日付、画像、リンクなどをまとめ、必要なデータを渡すだけで、複数の場所で再利用できます。 トップページに表示する最新記事。 ブログ一覧ページに並べる記事カード 関連記事として表示する小さなカード。 れらは見た目やサイズに違いがあっても、設計の考え方としては共通化できます。 このように、UIを部品として考えられることは、アプリケーションが大きくなるほど重要になります。 もし、すべてのHTML、CSS、JavaScriptがひとつの大きなファイルにまとまっていたら、変更の影響範囲が分かりにくくなります。 ボタンの見た目を少し変えたいだけなのに、他の画面に影響するかもしれない。 カードの構造を修正したいだけなのに、どこで同じようなUIが使われているのか分からない。 このような状態になると、開発速度も保守性も下がってしまいます。 Reactでは、UIをコンポーネントとして分けることで、責務を明確にできます。 このコンポーネントは表示だけを担当する。 このコンポーネントはデータを受け取ってカードとして表示する。 このコンポーネントはフォームの入力状態を管理する。 このコンポーネントはページ全体のレイアウトを担当する。 こうした役割分担ができることで、コードの見通しが良くなります。 また、Reactのコンポーネント設計は、単にコードを分割するためだけのものではありません。UIそのものを構造化して考えるための考え方でもあります。 大きなページをいきなり作ろうとすると、どうしても複雑に見えます。しかし、ページをセクションに分け、セクションをカードやボタンに分け、それぞれを小さなコンポーネントとして設計すれば、複雑な画面も段階的に組み立てられます。 今回のポートフォリオ制作でも、この考え方はかなり重要でした。 トップページ、ブログ一覧、ブログ詳細、プロジェクト表示、リンクセクション、問い合わせフォームなど、それぞれのページには異なる役割があります。ただし、UIの考え方としては共通している部分も多くあります。 カードUI、セクション見出し、リンク、タグ、ボタン、読み込み表示、レイアウト構造。こうした共通要素をコンポーネントとして整理することで、サイト全体の統一感を保ちやすくなりました。 Reactは、単に画面を表示するためのライブラリではありません。UIを小さく分解し、再利用し、組み合わせながら、アプリケーション全体を構造化していくための技術だと感じています。
Reactが強力なのは、コンポーネントを作れることだけではありません。 state、props、composition といった仕組みを使うことで、複雑なUIの状態やデータの流れを整理しやすくなります。さらにTypeScriptを組み合わせることで、コンポーネント間で扱うデータの形を明確にでき、保守性を高めることができます。 まず、state はコンポーネントの中で変化する値を管理するために使います。 Webアプリケーションでは、ユーザーの操作によって画面の状態が変化します。 フォームに文字を入力する。 ボタンをクリックする。 タブを切り替える。 モーダルを開く。 ローディング状態になる。 エラーを表示する。 言語を切り替える。 カードを選択する。 こうした変化を扱うために、Reactの state は非常に重要です。 たとえば問い合わせフォームであれば、入力された名前、メールアドレス、件名、本文、送信中かどうか、エラーがあるかどうか、送信が完了したかどうか、といった状態を管理する必要があります。 これらを適切に整理しないと、フォームの挙動はすぐに複雑になります。入力値と表示がずれたり、送信中にもボタンが押せてしまったり、エラー表示のタイミングが不自然になったりします。 Reactでは、状態とUIを結びつけて考えることができます。 状態が変われば、それに応じて表示も変わる。 この考え方によって、インタラクティブなUIを比較的整理された形で実装できます。 次に、props は親コンポーネントから子コンポーネントへデータを渡すための仕組みです。 Reactでは、同じコンポーネントでも、渡すデータによって表示内容を変えられます。 たとえば、同じ BlogPostCard コンポーネントでも、渡す記事データが変われば、タイトル、概要、タグ、日付、画像、リンク先を変えて表示できます。つまり、UIの構造は再利用しながら、中身だけを差し替えることができます。 この仕組みは、一覧表示やカードUIと非常に相性が良いです。 ブログ記事一覧。 プロジェクト一覧。 スキル一覧。 外部リンク一覧。 画像ギャラリー。 関連記事。 こうしたUIでは、同じ見た目の枠に対して、異なるデータを流し込むことが多くあります。Reactの props を使うことで、表示ロジックを共通化しながら、データに応じた柔軟なUIを作ることができます。 さらに重要なのが、composition です。 Reactでは、小さなコンポーネントを組み合わせて大きなUIを作ります。この「組み合わせる」という考え方が、Reactらしい設計の中心にあります。 単にコンポーネントを細かく分ければ良いわけではありません。 どの単位で分けるのか。 どこまで共通化するのか。 どこからページ固有の実装にするのか。 状態はどの階層に持たせるのか。 どのコンポーネントは表示だけにするのか。 どのコンポーネントはロジックを持つのか。 こうした判断が必要になります。 今回のポートフォリオ制作でも、composition の考え方はかなり重要でした。 たとえば、ブログ詳細ページでは、本文だけでなく、画像ギャラリー、メッセージブロック、通常のテキストブロックなど、複数の表示パターンを扱う必要があります。これらをすべてひとつの巨大なコンポーネントに詰め込むと、すぐに見通しが悪くなります。 そこで、データの種類に応じて表示コンポーネントを分けることで、ブログ本文の構造を柔軟に扱えるようになります。 さらにTypeScriptを組み合わせることで、Reactの設計はかなり安定します。 TypeScriptを使うと、props の型、ブログ記事データの型、画像データの型、フォーム入力値の型、APIレスポンスの型などを明確にできます。 これは、アプリケーションが大きくなるほど効果を感じます。 たとえば、ブログ記事には title、slug、excerpt、tags、published_at、cover_image_url などの情報があります。これらの型が曖昧なままだと、実装中に存在しないプロパティを参照したり、null の可能性を見落としたり、表示時にエラーが起きたりします。 TypeScriptを使うことで、そうした問題に早い段階で気づきやすくなります。 特に、Next.jsやSupabaseと組み合わせる場合、フロントエンドとバックエンドの間でデータ構造を正しく扱うことが重要になります。 データベースにある値を取得し、それをReactコンポーネントに渡し、画面に表示する。 この一連の流れに型があることで、コードの信頼性はかなり高くなります。 React、state、props、composition、TypeScript。 これらを組み合わせることで、複雑なUIをただ力技で作るのではなく、構造として整理しながら実装できます。 現代的なWebアプリケーションでは、UIはどんどん複雑になっています。静的なページだけではなく、フォーム、アニメーション、データ取得、エラー処理、ローディング、言語切り替え、認証、権限管理など、多くの状態を扱う必要があります。 その複雑さに向き合うための土台として、Reactの設計思想は非常に強力だと感じています。
ReactはUIを構築するためのライブラリですが、実際のWebアプリケーション開発では、UIだけで完結することはほとんどありません。 ページルーティング。 SEO。 メタデータ管理。 画像最適化。 サーバーレンダリング。 静的生成。 API連携。 データベースとの接続。 フォーム処理。 メール送信。 アニメーション。 外部サービスとの連携。 実用的なWebアプリケーションを作るには、こうした多くの要素が必要になります。 そこで重要になるのが、Next.jsのようなReactフレームワークです。 Next.jsを使うことで、Reactをベースにしながら、より実用的なWebアプリケーションを構築しやすくなります。 たとえばブログサイトを作る場合、単に記事本文を表示できればよいわけではありません。 記事一覧ページが必要です。 記事詳細ページが必要です。 各記事には固有のURLが必要です。 slug によるルーティングが必要です。 検索エンジン向けのメタデータも必要です。 OGP画像、タイトル、descriptionも設定したくなります。 記事の公開状態も管理する必要があります。 React単体でも実装はできますが、Next.jsを使うことで、こうしたページ構成、ルーティング、メタデータ管理をより扱いやすくなります。 今回のポートフォリオ制作でも、Next.jsはアプリケーション全体の基盤として重要な役割を持っていました。 トップページでは、インタラクティブなUIや3D表現を見せる。 ブログ一覧では、記事データを取得して表示する。 ブログ詳細では、slug に応じた記事を表示する。 プロジェクトページでは、制作物を整理して見せる。 問い合わせページでは、フォーム送信を扱う。 各ページで、適切なメタデータを設定する。 このように、ポートフォリオサイトであっても、実際には複数の機能を持つWebアプリケーションになります。 Next.jsを使うことで、Reactのコンポーネント設計を活かしながら、ページ単位の構成やサーバー側の処理も含めて整理できます。 さらに、Supabaseのようなバックエンドサービスと組み合わせることで、ReactとNext.jsの活用範囲はさらに広がります。 ブログ記事をSupabaseのPostgreSQLで管理し、公開済みの記事だけを取得して表示する。 画像URL、タグ、公開日、本文、slug などをデータベースで管理する。 フロントエンド側では、取得したデータをReactコンポーネントに渡して表示する。 こうすることで、記事データをコードに直接書くよりも、拡張性のある構成になります。 また、問い合わせフォームでは、Resendのようなメール送信サービスと組み合わせることで、ユーザーからのメッセージをメールとして受け取ることができます。フォームの入力、バリデーション、送信処理、完了表示、エラー表示といった一連の流れも、ReactとNext.jsを使うことで整理しやすくなります。 スタイリングにはTailwind CSSを組み合わせることで、コンポーネント単位でUIを調整しやすくなります。アニメーションにはFramer Motionを使うことで、UIの表示や遷移に自然な動きを加えられます。さらにReact Three Fiberを使えば、通常のDOMベースのUIだけでなく、3D表現もReactの構成の中に取り込めます。 このように、Reactは単体で完結する技術というよりも、周辺技術と組み合わせることで強さを発揮する技術だと感じています。 Reactを中心に、Next.jsでアプリケーションの骨格を作る。 TypeScriptで型安全性を高める。 Tailwind CSSでUIを構築する。 Supabaseでデータを管理する。 Framer Motionでアニメーションを加える。 React Three Fiberで3D表現を扱う。 必要に応じて、ResendやStripeのような外部サービスと連携する。 この組み合わせによって、静的なWebサイトから、フルスタック寄りのWebアプリケーションまで構築できます。 今回のポートフォリオ制作でも、Reactは中心的な役割を持っていました。ただし、Reactだけですべてを作ったわけではありません。 Reactを中心にして、Next.js、Supabase、Tailwind CSS、Framer Motion、React Three Fiberなどを組み合わせることで、単なるプロフィールサイトではなく、技術ブログ、3D表現、コンテンツ管理、問い合わせ機能を含むWebアプリケーションとして構築できました。 Reactの良さは、こうした技術をつなぎやすいところにもあります。 UIをコンポーネントとして整理し、データをpropsとして渡し、状態をstateで管理し、ページ構成をNext.jsで扱い、外部サービスと連携する。 この流れを自然に作れることが、現代的なWeb開発におけるReactの大きな強みだと思います。 Reactは、ただ画面を作るための技術ではありません。複雑なUIを構造化し、データの流れを整理し、アプリケーション全体を拡張しやすい形にしていくための土台です。 今回の制作を通して、Reactは現代的なWebアプリケーション開発と非常に相性が良いと改めて感じました。 特に、Next.jsやTypeScriptと組み合わせることで、Reactは単なるUIライブラリを超えて、実用的なWebアプリケーションを作るための中心的な技術になります。 コンポーネント設計、状態管理、型安全性、ページ構成、データ連携、アニメーション、3D表現。 これらをひとつのWebサイトの中で扱えたことは、Reactの強さを実感する良い機会になりました。