Skip to content

Commit 824ba73

Browse files
authored
Feature: ability to use nullable listener in useListenableSelector (#377)
1 parent 0a6d65a commit 824ba73

File tree

2 files changed

+38
-6
lines changed

2 files changed

+38
-6
lines changed

packages/flutter_hooks/lib/src/listenable_selector.dart

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ part of 'hooks.dart';
2525
///
2626
2727
R useListenableSelector<R>(
28-
Listenable listenable,
28+
Listenable? listenable,
2929
R Function() selector,
3030
) {
3131
return use(_ListenableSelectorHook(listenable, selector));
@@ -34,7 +34,7 @@ R useListenableSelector<R>(
3434
class _ListenableSelectorHook<R> extends Hook<R> {
3535
const _ListenableSelectorHook(this.listenable, this.selector);
3636

37-
final Listenable listenable;
37+
final Listenable? listenable;
3838
final R Function() selector;
3939

4040
@override
@@ -49,7 +49,7 @@ class _ListenableSelectorHookState<R>
4949
@override
5050
void initHook() {
5151
super.initHook();
52-
hook.listenable.addListener(_listener);
52+
hook.listenable?.addListener(_listener);
5353
}
5454

5555
@override
@@ -63,8 +63,8 @@ class _ListenableSelectorHookState<R>
6363
}
6464

6565
if (hook.listenable != oldHook.listenable) {
66-
oldHook.listenable.removeListener(_listener);
67-
hook.listenable.addListener(_listener);
66+
oldHook.listenable?.removeListener(_listener);
67+
hook.listenable?.addListener(_listener);
6868
_selectorResult = hook.selector();
6969
}
7070
}
@@ -83,7 +83,7 @@ class _ListenableSelectorHookState<R>
8383

8484
@override
8585
void dispose() {
86-
hook.listenable.removeListener(_listener);
86+
hook.listenable?.removeListener(_listener);
8787
}
8888

8989
@override

packages/flutter_hooks/test/use_listenable_selector_test.dart

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,38 @@ void main() {
8585
listenable.dispose();
8686
});
8787

88+
testWidgets('null as Listener', (tester) async {
89+
const notFoundValue = -1;
90+
final testListener = ValueNotifier(false);
91+
final listenable = ValueNotifier(777);
92+
var result = 0;
93+
94+
await tester.pumpWidget(
95+
HookBuilder(
96+
builder: (context) {
97+
final shouldUseListener = useListenableSelector(testListener, () {
98+
return testListener.value;
99+
});
100+
101+
final actualListener = shouldUseListener ? listenable : null;
102+
103+
result = useListenableSelector(actualListener, () {
104+
return actualListener?.value ?? notFoundValue;
105+
});
106+
107+
return Container();
108+
},
109+
),
110+
);
111+
112+
expect(result, notFoundValue);
113+
testListener.value = true;
114+
115+
await tester.pump();
116+
117+
expect(result, listenable.value);
118+
});
119+
88120
testWidgets('update selector', (tester) async {
89121
final listenable = ValueNotifier(0);
90122
var isOdd = false;

0 commit comments

Comments
 (0)