Closed bcihanc closed 1 year ago
Hi!
creator.change
can be used for listening. It is better in my mind because it is just a normal creator that returns a wrapper class with previous and current value. You can use the value however you want, for example, having a Creator
I'm not too sure about listenSelf, why would someone listen to self? Creator has an API called readSelf though.
I don't want to create a second creator for just listen another creator. Maybe I can figure it out with change. Thanks mate 😊.
I close this.
final langLocalValueEmitter = Emitter<String>((ref, emit) async {
String? lang = await _langLocalValue.read();
if (lang == null) {
await _langLocalValue.write('en');
lang = 'en';
}
emit(lang);
}, keepAlive: true, name: 'languageLocalValue');
Watcher(listener: (ref) async {
final langChange = await ref.watch(langLocalValueEmitter.change);
if (langChange.before != null && langChange.after != langChange.before) {
_langLocalValue.write(langChange.after);
}
}, (context, ref, child) {
final lang = ref.watch(langLocalValueEmitter.asyncData).data;
return MaterialApp.router( );
})
I finally found a example for that. How can I listen emitter change without a Watcher?
How can I listen emitter change without a Watcher?
That depends on where you want to watch and what you want to do.
Option 1 - Using watcher like in your code. Is there a reason you don't like it? Adding a watcher is cheap.
Option 2 - Put the listen logic in a CreatorState
, watch it in didChangeDependencies
and dispose it dispose
. If you really hate repeating these two steps, then maybe use a mixin like this:
/// Add a creator to stateful widget that got disposed automatically when the
/// state is disposed.
mixin CreatorMixin<T extends StatefulWidget> on State<T> {
// A creator that is typically set in initState and updated in didChangeWidget
// as needed.
Creator? _creator;
set creator(Creator value) {
if (_creator == null) {
_creator = value;
} else {
ref.dispose(_creator!);
_creator = value;
ref.watch(_creator!);
}
}
late Ref ref;
@override
void didChangeDependencies() {
ref = context.ref;
if (_creator != null) {
ref.watch(_creator!);
}
super.didChangeDependencies();
}
@override
void dispose() {
if (_creator != null) {
ref.dispose(_creator!);
}
super.dispose();
}
}
Option 3 - If the logic is global, you can watch the creator in main()
. Something like:
final app = CreatorGraph(child: const MyApp());
await app.ref.watch(someEmitter);
Thanks for options. How about this?
extension RefX on Ref {
void listen<T>(Creator<T> creator, void Function(Change<T> change) change, {String? name, bool keepAlive = false, List<Object?>? args}) {
watch(Creator(
(ref) => change(ref.watch(creator.change)),
name: name ?? '${creator.name}_listen',
keepAlive: keepAlive,
args: args,
));
}
}
ref.listen(creator, (change) { });
or
extension CreatorExtension<T> on Creator<T> {
void listener(Ref ref, void Function(Change<T> change) cb, {String? name, bool keepAlive = false, List<Object?>? args}) {
ref.watch(Creator(
(ref) => cb(ref.watch(change)),
name: name ?? '${infoName}_listen',
keepAlive: keepAlive,
args: args,
));
}
}
creator.listener(ref, (change) {});
Hi, your options are fine. Just remember to make the temporary creator stable (with args) if the ref
in your last line could rebuild by others. For example:
final someCreator = Creator((ref) {
ref.watch(fooCreator);
ref.listen(barCreator, (change) { print(change); }, args: ["some args to keep it stable"]);
return "something";
});
Though personally I would prefer:
final barLogger = Creator((ref) => print(ref.watch(barCreator.change)));
final someCreator = Creator((ref) {
ref.watch(fooCreator);
ref.watch(barLogger);
return "something";
});
Thanks mate, I'm gonna use listen out of context like this.
extension RefX on Ref {
void listen<T>(CreatorBase<FutureOr<T>> creator, void Function(Change<T> change) onChange, {String? name, bool keepAlive = false, List<Object?>? args}) {
if (creator is Creator<T>) {
watch(Creator((ref) {
onChange(ref.watch(creator.change));
}, name: name, keepAlive: keepAlive, args: args));
} else if (creator is Emitter<T>) {
watch(Emitter((ref, emit) async {
onChange(await ref.watch(creator.change));
}, name: name, keepAlive: keepAlive, args: args));
} else {
throw Exception('creator must be Creator or Emitter');
}
}
}
main() {
await globalRef.read(langLocalValueEmitter);
globalRef.listen(langLocalValueEmitter, (change) {
if (change.before != null && change.after != change.before) {
_langLocalValue.write(change.after);
}
});
}
runApp(...)
Hi, once again thanks for this great package 👍
Is there listen and listenSelf methods equivalents in Creator?