flutter_hooks
flutter_hooks copied to clipboard
Trigger a callback when value listenable changes
Is your feature request related to a problem? Please describe.
Having a big and complicated screen, that is optimised using useValueNotifier instead of useState, often there is a need to do something when value notifier changes.
Using useValueListenable would trigger rebuild, which is unwanted due to rebuilds optimisation
Describe the solution you'd like
There is a way to add and remove listener to value notifier. This could be utilised to build a useValueListenableChanged hook, similar to useValueChanged hook that is present already.
Describe alternatives you've considered
useValueChanged hook works on a regular variable, not on valueListenable
Additional context Here is what seemed to have worked. If there is no negative feedback I can make a PR:
import 'package:flutter/foundation.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
useValueListenableChanged<T>(
ValueListenable<T> listenable, Function(T value) valueListenableChanged) {
return use(
_UseValueListenableChangedHook(listenable, valueListenableChanged));
}
class _UseValueListenableChangedHook<T> extends Hook {
const _UseValueListenableChangedHook(
this.valueListenable, this.valueListenableChanged);
final Function(T value) valueListenableChanged;
final ValueListenable<T> valueListenable;
@override
_ValueListenableChangedState createState() =>
_ValueListenableChangedState<T>();
}
class _ValueListenableChangedState<T>
extends HookState<dynamic, _UseValueListenableChangedHook<T>> {
_ValueListenableChangedState();
late VoidCallback _valueListenableChanged;
@override
void initHook() {
_valueListenableChanged = () {
hook.valueListenableChanged(hook.valueListenable.value);
};
hook.valueListenable.addListener(_valueListenableChanged);
}
@override
void dispose() {
hook.valueListenable.removeListener(_valueListenableChanged);
}
@override
build(BuildContext context) {}
@override
String get debugLabel => 'useValueListenableChanged';
@override
Object? get debugValue => hook.valueListenable;
}