l

o

a

d

i

n

g

.

.

.

短期にFlutterを学習するブログ STEP4:状態管理の基礎

2026/02/23

Flutter プログラミング 学習

t f B! P L
eyecatch STEP3で静的な業務画面モックを作ったことで、「FlutterでUIを組む感覚」はかなり掴めてきたと思います。 ここから先、Flutterを業務アプリとして成立させるために、避けて通れないのが「状態管理」です。 でも、この段階でProvider や Riverpod に飛びつく必要はありません。 まずは setStateで何ができて、何ができないのか を、きちんと体感することが重要です。 ということで、今回は「状態管理」の基礎をやります。

setStateの限界を理解する

setStateは、Flutterにおける最も基本的な状態更新手段です。 StatefulWidgetの中で状態を変更し、UIを再描画させる。それだけの仕組み。 小さな画面や、単純なフォームであれば、setStateはとても分かりやすく、強力です。 ただし、少しでも画面が複雑になると、次のような違和感が出てきます。
・状態とUIが密結合になる ・どの変更が、どのUIに影響するのか追いづらい ・ロジックがWidgetの中に溜まり始める
この「違和感」を感じ取れるようになること自体が、このSTEPの重要なゴールです。

状態の持ち方と責務分離の考え方

Flutter初心者がやりがちなのは、「全部Widgetの中に書いてしまう」ことです。 最初はそれで問題ありません。 むしろ、無理に分離しない方が理解は早いです。 ただし、意識しておきたいのは、「UI」と「状態」は役割が違うという点です。
・UIは、状態をどう表示するか ・状態は、何がどう変わるか
この2つを頭の中で分けて考えるだけで、コードの見通しはかなり良くなります。 このSTEPでは、状態はWidgetのStateに閉じ込めるというルールだけ守れば十分です。

小規模画面における設計パターン

業務アプリでよくある小規模画面、たとえば検索フォームや入力フォーム。 こうした画面では、「1画面 = 1つのStatefulWidget」という構成が非常に相性が良いです。 画面全体の状態をそのWidgetが持ち、ユーザー操作に応じてsetStateで更新する。 複雑な抽象化をしなくても、十分に読みやすく、壊れにくい構造になります。 この段階では、拡張性よりも分かりやすさを優先するのが正解です。

成果物:入力 → 画面反映のフォーム

ここで、STEP4の成果物として、「入力した内容が即座に画面に反映される」シンプルなフォームを作ってみます。 ロジックは最小限、setStateの役割がはっきり分かる例です。

サンプルコード

lib/main.dart import 'package:flutter/material.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return const MaterialApp( home: SearchFormPage(), debugShowCheckedModeBanner: false, ); } } class SearchFormPage extends StatefulWidget { const SearchFormPage({super.key}); @override State<SearchFormPage> createState() => _SearchFormPageState(); } class _SearchFormPageState extends State<SearchFormPage> { String _inputName = ''; String _displayName = '未検索'; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('顧客検索'), ), body: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( '顧客名', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), ), const SizedBox(height: 8), Row( children: [ Expanded( child: TextField( onChanged: (value) { setState(() { _inputName = value; }); }, decoration: const InputDecoration( border: OutlineInputBorder(), hintText: '顧客名を入力してください', ), ), ), const SizedBox(width: 12), ElevatedButton( onPressed: () { setState(() { _displayName = _inputName.isEmpty ? '未検索' : _inputName; }); }, child: const Text('検索'), ), ], ), const SizedBox(height: 24), const Text( '検索結果(ダミー)', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), ), const SizedBox(height: 8), Text( _displayName, style: const TextStyle(fontSize: 18), ), ], ), ), ); } }

このコードのポイント

このフォームで重要なのは、「setStateがどこで呼ばれているか」です。 入力が変わった瞬間に状態を更新し、その結果が即座にUIへ反映される。 Flutterでは、状態が変わる → UIが再構築される という流れが、非常に素直に書けます。 この感覚を一度掴めると、状態管理が「難しいもの」ではなく、「制御できるもの」に変わります。

このSTEPのまとめ

このSTEPでは、高度な状態管理は一切扱っていません。 それで問題ありません。
・setStateで何ができるか ・どこから辛くなりそうか ・状態とUIを分けて考える感覚
この3点が分かれば、このSTEPは成功です。

あとがき

人気の投稿

このブログを検索

ごあいさつ

このWebサイトは、独自思考で我が道を行くユゲタの少し尖った思考のTechブログです。 毎日興味がどんどん切り替わるので、テーマはマルチになっています。 もしかしたらアイデアに困っている人の助けになるかもしれません。

ブログ アーカイブ