2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【React 19】7000行の App.tsx で挑む、AI時代の「超」個人開発アーキテクチャ

2
Last updated at Posted at 2026-04-12

読了目安:約10分

はじめに:なぜ「あえて」1ファイルなのか

モダンなフロントエンド開発において、コンポーネントの分割は「正義」とされます。しかし、個人開発の極致において、コンポーネントを 1 ファイルに集約する「Single File Architecture」は、圧倒的なプロトタイピング速度と、グローバルステート管理の簡略化という強力なメリットをもたらします。

特に2026年現在、Google Antigravity のような強力な AI エージェントをペアプログラマに据える場合、コードの「物理的な距離の近さ」が AI のコンテキスト理解を助け、開発効率を爆発させる鍵となります。

本記事では、筆者が開発した「数値分析カウンター」の 7000 行に及ぶ App.tsx を解剖し、大規模な再帰構造を持つアプリを 1 ファイルで破綻させずに実装するテクニックを詳細に解説します。

本記事で解説する「数値分析カウンター」の実物はこちら
https://numerical-analysis-counter.web.app/
※これらすべての機能が、1枚の App.tsx に凝縮されています。

🔰 初心者向け:Reactコンポーネントとは?
Reactでは、画面の部品(ボタン、入力欄、リストなど)を「コンポーネント」という単位で作ります。通常はこれらを別々のファイルに分けて管理しますが、本記事ではあえて「全部1つのファイル」にまとめる手法を紹介しています。


1. ステート設計:再帰的データ構造の管理

本アプリの核心は、AppNode という再帰的なインターフェースにあります。

interface AppNode {
  id: string;
  type: 'group' | 'counter';
  name: string;
  count?: number;
  children?: AppNode[];
  // ...ほか属性
}

この「木構造」を React の単一の tree ステートで管理しています。Redux や Context API を介さず、トップダウンで Props を流し込む「Props Drilling」をあえて採用していますが、これはエージェント駆動開発において「データの流れを静的に解析しやすい」という大きな利点に繋がります。

🔰 初心者向け:Props Drilling(プロップス・ドリリング)とは?
親から子、さらにその孫へと、バケツリレーのようにデータ(Props)を渡していくことです。階層が深いと管理が大変になると言われますが、1ファイル内であれば「どこからどこへデータが行ったか」をAIや検索機能ですぐに追いかけられるため、あえてこのシンプルな方法をとっています。

🔰 初心者向け:再帰(さいき)構造とは?
「箱の中にさらに箱が入っている」ような構造のことです。今回のカウンターアプリでは「グループの中にまたグループを作れる」仕組みを実現するために、自分自身と同じ形を繰り返すこのデータ構造を使っています。

2. 実装のツボ:再帰的な集計ロジックと最適化

0を除外する集計アルゴリズム

カウンターアプリを「分析ツール」に昇格させる機能が、再帰的な数値集計です。
特に「0を分母に含めない平均計算」をオンオフできる機能は、習慣化アプリにおいては「サボった日(0入力)によってモチベーションが下がらない」ためにも、「0を含む事実ベースの集計」や「0を含まない行動ベースの集計」に不可欠です。

// コンポーネント外に配置することで、AIエージェントの可読性とテスト容易性を向上
const calculateRecursiveStats = (node: AppNode, unlockedBoxIds: string[]): { total: number, avg: string } => {
  const counters = getAllCounters(node, unlockedBoxIds, true);
  const total = counters.reduce((sum, c) => sum + (c.count || 0), 0);
  const includeZero = node.includeZeroInAverage;
  const denominator = includeZero 
    ? counters.length 
    : counters.filter(c => (c.count || 0) > 0).length;

  const avg = denominator > 0 ? (total / denominator).toFixed(1) : "0.0";
  return { total, avg };
};

React 19 では React Compiler が標準搭載されているため、かつてのような useMemo(計算結果の保存)を人間が手動で行う必要はありません。ロジックをコンポーネント外に純粋関数として切り出すだけで、AI はその意図を正確に汲み取り、最適化された描画パイプラインに乗せてくれます。

3. パフォーマンスと最新機能:React 19 の恩恵

1 ファイル 7000 行となると再レンダリング(画面の描き直し)のコストが懸念されますが、React 19 の進化がそれを解決しました。

  1. メタデータのネイティブサポート:
    これまで useEffect という機能で無理やり書き換えていたページのタイトル(<title>)などを、JSX 内に直接書けるようになりました。
  2. createPortal の戦略的使用:
    モーダル(ポップアップ画面)などは、見た目上は深い階層にあっても、DOM(Webページの構造)としては一番外側に配置する仕組みです。これにより、レイアウトの計算が複雑になるのを防ぎます。
  3. エージェント・フレンドリーな構造:
    Google Antigravity での開発では、ファイルが分割されているよりも、1 つのファイルに全コンテキストが載っている方が、AI が「どの関数がどこに影響するか」を誤解するリスクが激減します。

4. 他の手法(Redux, Context)との比較

手法 メリット 2026年視点の評価
Single State (採用) 究極のシンプルさ AI との相性が最高。 1 ファイルに情報が凝縮されているため、AI 提案の精度が向上。
Context API バケツリレー不要 1 ファイル内であれば Props 渡し(バケツリレー)の方が、AI にとっての流れが明確。
Zustand / Recoil 部分的な更新が得意 データの整合性を保つのが難しくなる場合がある。今回は「全体の一貫性」を優先。

結論

「1 ファイル 1000 行ルール」は、人間だけでコードベースを把握しきれなかった時代のものです。

Gemini で「実装したい機能要件」を詰めた高度なプロンプトを練り、Google Antigravity という強力なAIエージェントに施工を任せる現代において、コードの物理的な距離の近さこそが、開発効率を最大化する正解かもしれません。本プロジェクトは、人間と AI が「巨大な 1 枚のキャンバス」を共有して描く、新しい開発スタイルの社会実験でもあります。


改めまして、Miyokiといいます。
初投稿の記事を最後まで読んでいただき、ありがとうございます。
普段は「Kawaii Future Bass」のBGM動画を趣味で投稿しています。
別角度でnoteやZennでも「数値分析カウンター」についての投稿をしています。
アプリ開発・この記事の作成を含めてかなりAIに頼っていたので、間違いがあるかもしれません。
お気軽にコメントで教えていただけると嬉しいです。


関連リンク

  • GitHub(README)

  • 数値分析カウンター(アプリ)

  • 制作記録(note)

  • BGM動画(Youtube)

2
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?