Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions lib/src/state_consumer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,14 @@ class StateConsumer<C extends IStateController<S>, S extends Object>
class _StateConsumerState<C extends IStateController<S>, S extends Object>
extends State<StateConsumer<C, S>> {
late C _controller;
late S _previousState;
late S _previousState, _visibleState;

@override
void didChangeDependencies() {
_controller =
widget.controller ?? ControllerScope.of<C>(context, listen: false);
_previousState = _controller.state;
_visibleState = _controller.state;
_subscribe();
super.didChangeDependencies();
}
Expand All @@ -86,6 +87,7 @@ class _StateConsumerState<C extends IStateController<S>, S extends Object>
_controller =
newController ?? ControllerScope.of<C>(context, listen: false);
_previousState = _controller.state;
_visibleState = _controller.state;
_subscribe();
}

Expand All @@ -108,6 +110,8 @@ class _StateConsumerState<C extends IStateController<S>, S extends Object>
_previousState = newState;
widget.listener?.call(context, _controller, oldState, newState);
if (widget.buildWhen?.call(oldState, newState) ?? true) {
_visibleState = newState;

// Rebuild the widget when the state changes.
switch (SchedulerBinding.instance.schedulerPhase) {
case SchedulerPhase.idle:
Expand All @@ -132,6 +136,7 @@ class _StateConsumerState<C extends IStateController<S>, S extends Object>
DiagnosticsProperty<IStateController<S>>('Controller', _controller),
)
..add(DiagnosticsProperty<S>('State', _controller.state))
..add(DiagnosticsProperty<S>('Visible state', _visibleState))
..add(
FlagProperty(
'isProcessing',
Expand All @@ -144,7 +149,7 @@ class _StateConsumerState<C extends IStateController<S>, S extends Object>

@override
Widget build(BuildContext context) =>
widget.builder?.call(context, _controller.state, widget.child) ??
widget.builder?.call(context, _visibleState, widget.child) ??
widget.child ??
const SizedBox.shrink();
}
21 changes: 14 additions & 7 deletions test/widget/state_consumer_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -90,14 +90,16 @@ void _$baseGroup() => group('base - ', () {
testWidgets('should not rebuild when buildWhen returns false', (
tester,
) async {
final controller = FakeController();
final controller1 = FakeController();
final controller2 = FakeController();

await tester.pumpWidget(
TestUtil.appContext(
child: ControllerScope.value(
controller,
child: StateConsumer(
controller: controller,
child: StateConsumer(
controller: controller1,
buildWhen: (previous, current) => true, // Outer rebuild
builder: (contex, state, child) => StateConsumer(
controller: controller2,
buildWhen: (previous, current) => false, // No rebuild
builder: (context, state, child) => Text('$state'),
),
Expand All @@ -107,12 +109,17 @@ void _$baseGroup() => group('base - ', () {

expect(find.text('0'), findsOneWidget);

controller.add(1);

controller2.add(1);
await tester.pumpAndSettle(); // Rebuild should not happen

expect(find.text('1'), findsNothing); // Should still show 0
expect(find.text('0'), findsOneWidget);

controller1.add(1);
await tester.pumpAndSettle(); // Trigger outer rebuild

expect(find.text('1'), findsNothing); // Should still show 0
expect(find.text('0'), findsOneWidget);
});

testWidgets('should use child if builder is not provided', (tester) async {
Expand Down