React hooks for Flutter. Hooks are a new kind of object that manages a Widget life-cycles. They are used to increase code sharing between widgets and as a complete replacement for StatefulWidget.
MIT License
3.06k
stars
175
forks
source link
A ticker created by `useSingleTickerProvider` is not muted properly #431
Describe the bug
Suppose you have Screen A using useSingleTickerProvider.
Screen A is rebuilt when you push from Screen A to Screen B and when you pop from Screen B to Screen A.
To Reproduce
With the code below,
Verify that Screen A is rebuilt when you press the button on Screen A.
Verify that Screen A is rebuilt when you press the back button on Screen B
In other words, there seemed to be a difference in the implementation of useSingleTickerProvider and SingleTickerProviderStateMixin.
As a test, I changed useSingleTickerProvider based on the implementation of SingleTickerProviderStateMixin as shown below, and it worked as expected.
changed useSingleTickerProvider
```dart
/// Creates a single usage [TickerProvider].
///
/// See also:
/// * [SingleTickerProviderStateMixin]
TickerProvider useSingleTickerProvider({List
Describe the bug Suppose you have Screen A using
useSingleTickerProvider
. Screen A is rebuilt when you push from Screen A to Screen B and when you pop from Screen B to Screen A.To Reproduce
With the code below,
Code example
```dart import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter_animate/flutter_animate.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; void main() { runApp(const MaterialApp(home: AScreen())); } class AScreen extends HookWidget { const AScreen({super.key}); @override Widget build(BuildContext context) { print('Screen A: build'); final ticker = useSingleTickerProvider(); final controller = useAnimationController(vsync: ticker); return Scaffold( appBar: AppBar(title: const Text('Screen A')), body: Center( child: FilledButton( onPressed: () { Navigator.of(context).push( MaterialPageRoute(builder: (context) => const BScreen()), ); }, child: const Text('Go to Screen B'), ).animate(controller: controller).shake(), ), ); } } class BScreen extends StatelessWidget { const BScreen({super.key}); @override Widget build(BuildContext context) { return Scaffold(appBar: AppBar(title: const Text('Screen B'))); } } ```
Expected behavior It is expected that a push to Screen B and a pop from Screen B will not rebuild Screen A.
My thoughts When I didn't prepare the
AnimationController
myself and managed it insideAnimate
Widget as shown below, it worked as expected.use ticker created by SingleTickerProviderStateMixin
```dart import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter_animate/flutter_animate.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; void main() { runApp(const MaterialApp(home: AScreen())); } class AScreen extends HookWidget { const AScreen({super.key}); @override Widget build(BuildContext context) { print('Screen A: build'); return Scaffold( appBar: AppBar(title: const Text('Screen A')), body: Center( child: FilledButton( onPressed: () { Navigator.of(context).push( MaterialPageRoute(builder: (context) => const BScreen()), ); }, child: const Text('Go to Screen B'), ).animate().shake(), ), ); } } class BScreen extends StatelessWidget { const BScreen({super.key}); @override Widget build(BuildContext context) { return Scaffold(appBar: AppBar(title: const Text('Screen B'))); } } ```
In other words, there seemed to be a difference in the implementation of
useSingleTickerProvider
andSingleTickerProviderStateMixin
. As a test, I changeduseSingleTickerProvider
based on the implementation ofSingleTickerProviderStateMixin
as shown below, and it worked as expected.changed useSingleTickerProvider
```dart /// Creates a single usage [TickerProvider]. /// /// See also: /// * [SingleTickerProviderStateMixin] TickerProvider useSingleTickerProvider({List
reference
Thank you.