読了目安:約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 の進化がそれを解決しました。
-
メタデータのネイティブサポート:
これまでuseEffectという機能で無理やり書き換えていたページのタイトル(<title>)などを、JSX 内に直接書けるようになりました。 -
createPortalの戦略的使用:
モーダル(ポップアップ画面)などは、見た目上は深い階層にあっても、DOM(Webページの構造)としては一番外側に配置する仕組みです。これにより、レイアウトの計算が複雑になるのを防ぎます。 -
エージェント・フレンドリーな構造:
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)
-
開発記(Zenn)
https://zenn.dev/miyoki347/articles/c6ba71be773e47 -
制作の進捗(X/旧Twitter)
- BGM動画(Youtube)