From 61ae94187bdcdbde1f98889fb5b581c32a58ce2a Mon Sep 17 00:00:00 2001 From: Des1ynY Date: Fri, 13 Feb 2026 22:30:17 +0500 Subject: [PATCH] fix: preserve visible state in state consumer --- lib/src/state_consumer.dart | 9 +++++++-- test/widget/state_consumer_test.dart | 21 ++++++++++++++------- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/lib/src/state_consumer.dart b/lib/src/state_consumer.dart index f1dc071..6b1b165 100644 --- a/lib/src/state_consumer.dart +++ b/lib/src/state_consumer.dart @@ -63,13 +63,14 @@ class StateConsumer, S extends Object> class _StateConsumerState, S extends Object> extends State> { late C _controller; - late S _previousState; + late S _previousState, _visibleState; @override void didChangeDependencies() { _controller = widget.controller ?? ControllerScope.of(context, listen: false); _previousState = _controller.state; + _visibleState = _controller.state; _subscribe(); super.didChangeDependencies(); } @@ -86,6 +87,7 @@ class _StateConsumerState, S extends Object> _controller = newController ?? ControllerScope.of(context, listen: false); _previousState = _controller.state; + _visibleState = _controller.state; _subscribe(); } @@ -108,6 +110,8 @@ class _StateConsumerState, 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: @@ -132,6 +136,7 @@ class _StateConsumerState, S extends Object> DiagnosticsProperty>('Controller', _controller), ) ..add(DiagnosticsProperty('State', _controller.state)) + ..add(DiagnosticsProperty('Visible state', _visibleState)) ..add( FlagProperty( 'isProcessing', @@ -144,7 +149,7 @@ class _StateConsumerState, 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(); } diff --git a/test/widget/state_consumer_test.dart b/test/widget/state_consumer_test.dart index 67d1d31..2667035 100644 --- a/test/widget/state_consumer_test.dart +++ b/test/widget/state_consumer_test.dart @@ -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'), ), @@ -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 {