github.com/rrousselGit/flutter_hooks(開始URL: https://github.com/rrousselGit/flutter_hooks?tab=readme-ov-file#existing-hooks)の翻訳及び補足をしてあります。
本ブログの(上記flutter_hooksの)翻訳および解説の目次頁(構成上のトップページ)は次のURLになります。
本頁は、上記のうちの、「Motivation」の章の翻訳および解説頁になります。
Motivation
StatefulWidgetには大きな問題があります。
initState や dispose のロジックを再利用することが非常に難しいのです。
以下はその事例(AnimationControllerの場合)です。
class Example extends StatefulWidget {
const Example({super.key, required this.duration});
final Duration duration;
@override
_ExampleState createState() => _ExampleState();
}
class _ExampleState extends State<Example> with SingleTickerProviderStateMixin {
late final AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(vsync: this, duration: widget.duration);
}
@override
void didUpdateWidget(Example oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.duration != oldWidget.duration) {
_controller.duration = widget.duration;
}
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container();
}
}
対応1)このロジックのほぼすべてを最初から再実装する:
AnimationController を使用するすべてのウィジェットは、このロジックのほぼすべてを最初から再実装する必要がありますが、これはもちろん望ましくありません。
対応2)Dart ミックスインを使用する:
Dart ミックスインはこの問題を部分的に解決できます。しかし次の問題が発生します。
- 特定のミックスインはクラスごとに 1 回のみ使用できます。
- ミックスインとクラスは同じオブジェクトを共有します。
つまり、2 つのミックスインが同じ名前で変数を定義した場合、コンパイル失敗から不明な動作まで結果が異なる場合があります。
対応3)Hooks を利用する:
class Example extends HookWidget {
const Example({super.key, required this.duration});
final Duration duration;
@override
Widget build(BuildContext context) {
final controller = useAnimationController(duration: duration);
return Container();
}
}
このコードは機能的には前の例と同等です。この場合も、AnimationController は破棄され、Example.duration が変更されると継続時間が更新されます。しかし、あなたはおそらく次のように考えているでしょう。
残りのロジックはどこへ行ったの?
残りのロジックは(Hooksに直接含まれる関数) useAnimationController に移動しました。
これをHooksといいます。
フックは、いくつかの特殊性を持った新しい種類のオブジェクトです:
- Hooksをmixinしたウィジェットのbuildメソッドでのみ使用できます。
- 同じHooksは任意に何度でも再利用できます。次のコードは 2 つの独立したAnimationControllerを定義しており、ウィジェットの再構築時にそれらは正しく保持されます。
Widget build(BuildContext context) {
final controller = useAnimationController();
final controller2 = useAnimationController();
return Container();
}
- Hooksは、互いに、またウィジェットから完全に独立しています。 これは、他の場所で使用できる様にパッケージに抽出し、共有公開できる、ということです。