You can use the flutter_hooks package.
The method useEffect()
is the equivalent of initState
+ didUpdateWidget
+ dispose
.
useEffect(() {
// This is "initState". Run your methods here
uiController.getData();
// We could optionally return some "dispose" logic here, ex.,
// return subscription.cancel;
return null;
}, const [
// here specify custom keys that will rebuild the widget. It's "didUpdateWidget"
]);
As an example, we could use hooks to manually implement a fade-in animation, where a widget starts invisible and slowly appears.
If we were to use StatefulWidget, the code would look like this:
class FadeIn extends StatefulWidget {
const FadeIn({Key? key, required this.child}) : super(key: key);
final Widget child;
@override
State<FadeIn> createState() => _FadeInState();
}
class _FadeInState extends State<FadeIn> with SingleTickerProviderStateMixin {
late final AnimationController animationController = AnimationController(
vsync: this,
duration: const Duration(seconds: 2),
);
@override
void initState() {
super.initState();
animationController.forward();
}
@override
void dispose() {
animationController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: animationController,
builder: (context, child) {
return Opacity(
opacity: animationController.value,
child: widget.child,
);
},
);
}
}
Using hooks, the equivalent would be:
class FadeIn extends HookWidget {
const FadeIn({Key? key, required this.child}) : super(key: key);
final Widget child;
@override
Widget build(BuildContext context) {
// Create an AnimationController. The controller will automatically be
// disposed when the widget is unmounted.
final animationController = useAnimationController(
duration: const Duration(seconds: 2),
);
// useEffect is the equivalent of initState + didUpdateWidget + dispose.
// The callback passed to useEffect is executed the first time the hook is
// invoked, and then whenever the list passed as second parameter changes.
// Since we pass an empty const list here, that's strictly equivalent to `initState`.
useEffect(() {
// start the animation when the widget is first rendered.
animationController.forward();
// We could optionally return some "dispose" logic here
return null;
}, const []);
// Tell Flutter to rebuild this widget when the animation updates.
// This is equivalent to AnimatedBuilder
useAnimation(animationController);
return Opacity(
opacity: animationController.value,
child: child,
);
}
}