※ これは「どこまでAIに任せるか」という線引きの話ではありません。任せていい部分は任せて大丈夫です。ただ、出てきたコードの構造を見分ける知識がないと、あとから壊れやすい形になっていても気づけない、という話です。
1画面のうちは、useStateで何でも動く
未経験の方がAIと一緒にReactアプリを作るとき、最初の1画面は useState だけでだいたい何でもうまくいきます。
function Cart() {
const [items, setItems] = useState<Item[]>([]);
// items を使って画面を組み立てる
}
1つのコンポーネントの中で状態を持って、そのコンポーネントの中で表示する。これだけなら迷う要素がありません。
画面が増えた瞬間に、崩れ方が変わる
問題は、同じ items(カートの中身)を、離れた場所にある別のコンポーネントでも使いたくなったときです。
例えば「ヘッダーのカートアイコンにも件数を出したい」となると、items を持っている Cart から、Header まで値を届ける必要があります。あいだにコンポーネントが挟まっていると、こうなりがちです。
// Before: 使わない層にも props を素通りさせる(プロップスドリリング)
function App() {
const [items, setItems] = useState<Item[]>([]);
return <Layout items={items} />;
}
function Layout({ items }: { items: Item[] }) {
// Layout 自身は items を使わないのに、中継のために受け取る
return (
<>
<Header items={items} />
<Cart items={items} />
</>
);
}
function Header({ items }: { items: Item[] }) {
return <span>カート: {items.length}件</span>;
}
Layout は items を一切使っていないのに、中継のためだけに受け取っています。これがプロップスドリリングと呼ばれる状態です。コンポーネントが2〜3層ならまだ耐えられますが、画面が増えて階層が深くなるほど、「この props、どこから来てどこで使われているんだっけ」を追うコストが上がっていきます。
AIに機能追加を頼んだときも、この構造を知らないまま「カート件数をここにも表示して」とだけ頼むと、AIが同じprops中継の階層を1本増やす形で対応してくることがあります。動きはしますが、直すたびに中継コンポーネントが増えていく状態です。
Context APIで、中継をなくす
Reactには、この中継を省略する仕組みとして Context API があります。
const CartContext = createContext<Item[]>([]);
function App() {
const [items, setItems] = useState<Item[]>([]);
return (
<CartContext.Provider value={items}>
<Layout />
</CartContext.Provider>
);
}
function Layout() {
// items を受け取る必要がなくなる
return (
<>
<Header />
<Cart />
</>
);
}
function Header() {
const items = useContext(CartContext); // 中継なしで直接取得
return <span>カート: {items.length}件</span>;
}
Layout が items を受け取らずに済むようになりました。Header は必要な場所で直接 useContext を呼んで値を取りに行きます。中継の層を追う必要がなくなる分、コンポーネントを見たときに「このコンポーネント自身が何をしているか」が読みやすくなります。
もう1つの罠: 二重管理
Context化したあとにありがちなのが、Providerで管理している値を、子コンポーネント側でも useState にコピーして持ってしまうケースです。
function Cart() {
const contextItems = useContext(CartContext);
const [localItems, setLocalItems] = useState(contextItems); // 罠: コピーしてしまう
// 以降 localItems を更新しても、Contextの本体は更新されない
}
こうなると、片方だけ更新されて表示がズレる、という不具合が起きます。「値はどこか1箇所だけが正とする」を崩さないことが、状態管理で一番大事な原則です。
AIに頼むときに意識すること
機能を追加で頼むとき、「この値をどこで持つか」を先に自分で決めてから頼むと、AIの出力も安定します。
- 「1つのコンポーネントの中だけで完結する値」→
useStateのままでいい - 「複数の離れたコンポーネントで共有したい値」→ Contextに上げる、と明示して頼む
このひと言があるだけで、AIが中継propsを増やして対応するか、Contextを使って対応するかが変わることがあります。
まとめ
- 1画面のうちは
useStateで困らない - 画面が増えて共有したい値が出てきたら、propsの中継(プロップスドリリング)が起き始めるサイン
- Context APIで中継を省略できるが、子コンポーネント側でコピーして二重管理にしないよう注意する
未経験者向けの講座を運営しています
未経験から Next.js + Supabase + Claude Code で Webアプリを公開するまで を、全20セッションで体系化した教材です。Claude Code を学習パートナーにする CLAUDE.md と学習モード(learner / developer)の設計までセットで含みます。
- ▶ ライブデモ(インストール不要・無料で今すぐ見られます)→ https://trial-web-ayies128s-projects.vercel.app/?ref=qiita
- 教材完全版+月5,500円のメンタリング(全20セッション+チャット質問し放題)→ https://menta.work/plan/20251?ref=qiita
- 無料体験版(git clone して自分の手元で動かす・最初の数セッション分・⭐ Star もよろしくお願いします)→ https://github.com/ayies128/next-ai-camp-trial
- YouTube『AIエンジニア情報局』(AI×開発ニュースを1本5分でキャッチアップできる別運営チャンネル・無料)→ https://www.youtube.com/channel/UC1rXVD9WYsQPQEWZyd-A1KA/?ref=qiita
※ Qiita読者の方には易しすぎる内容なので、初心者の知り合いへの紹介や社内研修の参考としてどうぞ。