-
-
Notifications
You must be signed in to change notification settings - Fork 70
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Question about implementing of ref.listenSelf
in auth.dart
#14
Comments
Hi there, there are no dumb questions.
This is true. And it's also true for Why tho? That's because registering a callback which reactively listens to other providers (i.e. events) might be dangerous if performed asynchronously. Imagine a scenario in which we This is why the docs state this shouldn't be done in a (e.g.) Luckily, when using
Nonetheless, chances are I will edit that line out: obtaining |
Thank you very much for the response and detailed explanation. I really appreciate it! |
I wanted to further explore this behavior. Here's a full reproducible example: import 'dart:math';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'main.g.dart';
void main() {
runApp(const ProviderScope(child: MyApp()));
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Riverpod Demo',
theme: ThemeData(primarySwatch: Colors.blue),
home: const MyHomePage(title: 'Riverpod demo here we go!'),
routes: {'new-route': (context) => const MyWidget()},
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const <Widget>[
Text(
"Press the button to initialize the other screen and providers!")
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.of(context).pushNamed('new-route');
},
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
class MyWidget extends ConsumerWidget {
const MyWidget({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final a = ref.watch(stateProvider).when(
data: (data) => "$data",
error: (error, stackTrace) => "Error",
loading: () => "loading...",
);
return Scaffold(
body: Center(
child: InkWell(
onTap: () async {
Navigator.of(context).pop();
await Future.delayed(const Duration(seconds: 3));
try {
// won't work (remove try catch to see what happens)
print("Reading 1... ${ref.read(otherProvider)}");
} catch (e) {}
try {
// won't work (remove try catch to see what happens)
print("Reading 2... ${ref.read(stateProvider)}");
} catch (e) {}
},
child: Container(
color: Colors.amberAccent,
padding: const EdgeInsets.all(32),
child: Text(a),
),
),
),
);
}
}
@riverpod
Future<int> state(StateRef ref) async {
ref.onResume(() {
print("I am alive again!");
});
ref.onCancel(() {
print("I have no more listeners, I'm gonna be disposed!");
});
ref.onDispose(() {
print("I have been disposed!");
});
final result = await Future.delayed(
const Duration(seconds: 2),
() => Random().nextInt(10),
);
ref.listenSelf((previous, next) {
print("I have listened to myself: $next");
});
ref.listen(otherProvider, (previous, next) {
print("I have listened to other: $next");
});
ref.keepAlive();
return result;
}
@riverpod
Future<int> other(OtherRef ref) async {
ref.onResume(() {
print("[other] I am alive again!");
});
ref.onCancel(() {
print("[other] I have no more listeners, I'm gonna be disposed!");
});
ref.onDispose(() {
print("[other] I have been disposed!");
});
final result = await Future.delayed(
const Duration(seconds: 2),
() => Random().nextInt(10),
);
ref.listenSelf((previous, next) {
print("[other] I have listened to myself");
});
ref.keepAlive();
return result;
} I invite you to test this out, and to go in and out the pushed route (press the button and then the rectangle) - and read the logs. There's a few takeaways:
|
Hello,
I have a dumb question and apologize in advance if this isn't the correct place to ask it.
In auth.dart, the asynchronous
build()
calls_persistenceRefreshLogic()
which then callsref.listenSelf()
. According to the Riverpod docs,ref.listen()
shouldn't be called asynchronously.Does that guidance not specifically apply to
ref.listenSelf()
or this usage in general (i.e. if I wanted to callref.listen
in a similar method would it be okay)?The text was updated successfully, but these errors were encountered: