
Managing state
Prop drilling (プロップ・ドリリング)
Prop drilling(プロップ・ドリリング)とは、Reactなどのコンポーネントベースのフレームワークで、ある親コンポーネントから子コンポーネント、さらにその子コンポーネントへと、props(プロパティ)を何段階にもわたって渡していく状態を指します。
この概念は、Reactに限らずFlutterのような他のUIフレームワークでも広く見られます。Flutterでは、親ウィジェットから子ウィジェットへとデータやコールバック関数を渡していく形で同様の構造が現れます。多くの階層を通じてデータを伝搬させる必要がある場合、コードの可読性や保守性が低下しやすくなるため、適切な状態管理手法(例:ReactではContext APIやRedux、FlutterではProviderやRiverpodなど)を導入することが推奨されます。
Prop drilling
An example
Parent Widget(親)
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
/// variable declaration
bool isSoundEnabled = true;
/// function declaration
void updateSound(bool value) {
setState(() {
isSoundEnabled = value;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: TopScreen(
/// parameters
isSoundEnabled: isSoundEnabled,
updateSound: updateSound,
),
);
}
}
Child Widget (子ども)
class TopScreen extends StatelessWidget {
final bool isSoundEnabled;
final Function(bool) updateSound;
TopScreen({required this.isSoundEnabled, required this.updateSound});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Sound Settings')),
body: Center(
child: Switch(
value: isSoundEnabled,
onChanged: (value) {
updateSound(value);
},
),
),
);
}
}


Why Riverpod?
Managing state outside of a Widget’s lifestyle

Riverpodを使うと、アプリ全体で使いたいデータ(=状態)をWidgetの
外側で管理(=グローバル管理)できます。
たとえば「音をオン・オフする設定」や「ログインしているユーザー情報」などをどの画面からでも簡単に使えるようになります。
通常、状態をあるWidgetで定義すると、そのWidget内でしか使えません。
でもRiverpodを使えば…
✅ 他の画面(Widget)からも呼び出せる
✅ データの変更もどこからでもできる
✅ データが変われば、使っているWidgetが自動で再ビルドされる
Why Riverpod?
Managing state outside of a Widget’s lifestyle
/// type = bool
final soundEffectsProvider = NotifierProvider.autoDispose<SoundEffectsProvider, bool>(
SoundEffectsProvider.new,
);
class SoundEffectsProvider extends AutoDisposeNotifier<bool> {
@override
/// initial value
bool build() {
return true;
}
/// state function
void updateSound(value) {
state = value;
}
}
final isSoundEnabled = ref.watch(soundEffectsProvider);

final isSoundEnabled = ref.watch(soundEffectsProvider);

ref.read(soundEffectsProvider.notifer).updateSound()


final wordleViewControllerProvider = Provider<WordleViewController>(
/// ref object
(ref) => WordleViewController(ref),
);
class WordleViewController {
final Ref _ref;
/// access ref object
WordleViewController(this._ref);
/// using ref object to access other providers
KeyboardProvider get _keyboardState => _ref.read(keyboardProvider.notifier);
WordleProvider get _wordleState => _ref.read(wordleProvider.notifier);
SoundEffectsService get _soundEffectsService => _ref.read(soundEffectsServiceProvider);
}
RiverpodのProviderは、refオブジェクトを通じて他のプロバイダ(Provider)への参照や依存関係の取得を行うことができます。refは、プロバイダのコールバック関数(例:Provider, FutureProvider, StateNotifierProviderなど)に渡されるオブジェクトであり、他のプロバイダをref.watch()やref.read()などのメソッドを使って参照するために使用されます。
Conclusion
Feature | Prop Drilling | Riverpod |
✅️ Simple to Use | ✔ Very simple for small apps | ❌️ Slightly more setup |
🧠 Easy to Understand | ✔Clear where state comes from | ❌️ Indirection(you read from providers) |
📐 Scalablility | ❌️ Becomes messy in deep trees | ✔ Scales cleanly across large apps |
🔁 Reusability | ❌️ Hard to reuse logic cleany | ✔ Providers can be reused anywhre |
📚️ Testability | ❌️ UI and logic tightly coupled | ✔ Easily test logic in isolation |
📥️ Boilerplate | ✔ Less boilerplate upfront | ❌️ More boilerplate for small use cases |
📦️ Global Accese | ❌️ Must pass props everywhere | ✔ Access state from any widget |
🧩 Composition | ❌️ Harder to compose nested logic | ✔ Providers can depend on providers |
🧪 Debuggin | ✔ Straightforward(usually) | ❌️ Slightly more abstract |
特徴 | Prop Drilling | Riverpod |
✅️ シンプルさ | ✔ 小規模なアプリではとても簡単 | ❌️ 最初のセットアップが少し必要 |
🧠 理解のしやすさ | ✔状態の流れが明確 | ❌️ Provider経由で少し抽象的 |
📐 スケーラビリティ | ❌️ ツリーが深くなると煩雑に | ✔ Providerはどこでも再利用可能 |
🔁 再利用性 | ❌️ ロジックの再利用が難しい | ✔ Providers can be reused anywhre |
📚️ テストのしやすさ | ❌️ UIとロジックが密結合 | ✔ ロジックを個別にテストしやすい |
📥️ ボイラープレート | ✔ 初期の記述量が少ない | ❌️ 小規模な用途だとやや多め |
📦️ グローバルアクセス | ❌️ 毎回手動で状態を渡す必要あり | ✔ どのウィジェットからでもアクセス可能 |
🧩 ロジックの構成 | ❌️ ネストしたロジックの構造が難しい | ✔ Provider同士で依存関係を持てる |
🧪 デバッグ | ✔ 状態の流れがわかりやすい | ❌️ 少し抽象度が高くなることも |