diff --git a/README.md b/README.md index 254b6cc..89c9e94 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,20 @@ Now whenever `counter.value` changes (here using `counter.value++` in the `onPre That's all there is to it! +## Notifying listeners of deeper changes + +If you try to wrap a collection or object in a `ValueNotifier`, e.g. to track a set of values using `ValueNotifier>`, then modifying fields, or adding or removing values from the collection or object will not notify the listeners of the `ValueNotifier` that the value has changed (because the value itself has not changed). In this case you can call the extension method `notifyChanged()` to manually call the listeners. For example: + +```dart +final tags = ValueNotifier({}); + +void addOrRemoveTag(String tag, bool add) { + if ((add && tags.value.add(tag)) || (!add && tags.value.remove(tag))) { + tags.notifyChanged(); + } +} +``` + ## The code The `flutter_reactive_value` mechanism is extremely simple. [See the code here.](https://github.com/lukehutch/flutter_reactive_value/blob/main/lib/src/reactive_value_notifier.dart) diff --git a/lib/src/reactive_value_notifier.dart b/lib/src/reactive_value_notifier.dart index 49cf183..48b83a4 100644 --- a/lib/src/reactive_value_notifier.dart +++ b/lib/src/reactive_value_notifier.dart @@ -5,7 +5,12 @@ class _ListenerWrapper { void Function()? listener; } +/// Extend [ValueNotifier] so that [Element] objects in the build tree can +/// respond to changes in the value. extension ReactiveValueNotifier on ValueNotifier { + /// Fetch the [value] of this [ValueNotifier], and subscribe the element + /// that is currently being built (the [context]) to any changes in the + /// value. T reactiveValue(BuildContext context) { final elementRef = WeakReference(context as Element); // Can't refer to listener while it is being declared, so need to add @@ -29,4 +34,12 @@ extension ReactiveValueNotifier on ValueNotifier { addListener(listenerWrapper.listener!); return value; } + + /// Use this method to notify listeners of deeper changes, e.g. when a value + /// is added to or removed from a set which is stored in the value of a + /// `ValueNotifier>`. + void notifyChanged() { + // ignore: invalid_use_of_protected_member, invalid_use_of_visible_for_testing_member + notifyListeners(); + } }