Reactive<T> class
A widget that rebuilds when a ReactiveNotifier changes.
Similar to Flutter's ValueListenableBuilder but with additional features:
- Optional conditional rebuilds via
buildWhen - Side effects via
listener - Multiple notifier support via Reactive.multi
- Property selection via Reactive.select
- Async state handling via Reactive.async
- Auto-dispose by default via
autoDispose
Examples
Basic Usage
final counter = ReactiveNotifier<int>(0);
Reactive<int>(
notifier: counter,
builder: (context, value, child) => Text('Count: $value'),
)
// Update triggers rebuild
counter.value++;
Conditional Rebuild (buildWhen)
Only rebuild when specific conditions are met:
Reactive<int>(
notifier: counter,
buildWhen: (previous, current) => current > previous, // Only on increase
builder: (context, value, child) => Text('$value'),
)
Side Effects (listener)
Execute actions without rebuilding (e.g., show snackbar, navigate):
Reactive<int>(
notifier: counter,
listener: (context, value) {
if (value >= 10) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Reached $value!')),
);
}
},
builder: (context, value, child) => Text('$value'),
)
Conditional Listening (listenWhen)
Control when the listener is called:
Reactive<int>(
notifier: counter,
listenWhen: (previous, current) => current % 5 == 0, // Every 5th value
listener: (context, value) {
print('Milestone reached: $value');
},
builder: (context, value, child) => Text('$value'),
)
Child Optimization (Performance)
Problem: When the notifier changes, the entire builder function runs again,
recreating all widgets inside it - even widgets that don't depend on the value.
Solution: Pass static (unchanging) widgets via the child parameter.
These widgets are built once and reused on every rebuild, improving performance.
❌ Without child optimization (rebuilds everything):
Reactive<int>(
notifier: counter,
builder: (context, value, child) => Card(
child: Column(
children: [
const Icon(Icons.star, size: 50), // Rebuilt every time!
const Text('Your Score'), // Rebuilt every time!
const SizedBox(height: 10), // Rebuilt every time!
Text('$value', style: TextStyle(fontSize: 24)), // Needs rebuild
],
),
),
)
✅ With child optimization (only rebuilds what's needed):
Reactive<int>(
notifier: counter,
builder: (context, value, child) => Card(
child: Column(
children: [
child!, // Reused, never rebuilt!
Text('$value', style: TextStyle(fontSize: 24)), // Only this rebuilds
],
),
),
child: const Column(
children: [
Icon(Icons.star, size: 50),
Text('Your Score'),
SizedBox(height: 10),
],
),
)
When to use child:
- Icons, images, decorations that don't change
- Static text labels
- Complex widgets that are expensive to build
- Any widget that doesn't depend on the notifier's value
Disable Auto Dispose
By default, notifiers are automatically disposed when the widget is removed.
Set autoDispose: false if you manage the notifier lifecycle elsewhere:
Reactive<int>(
notifier: counter,
autoDispose: false, // Don't dispose, managed elsewhere
builder: (context, value, child) => Text('$value'),
)
See also:
- Reactive.multi for listening to multiple notifiers
- Reactive.select for rebuilding only when specific properties change
- Reactive.async for async operations with loading/error states
- ReactiveNotifier for the reactive value holder
- AsyncReactiveNotifier for async operations
- ReactiveProvider for sharing notifiers across the widget tree
- Inheritance
-
- Object
- DiagnosticableTree
- Widget
- StatefulWidget
- Reactive
- Available extensions
Constructors
-
Reactive({Key? key, required ReactiveNotifier<
T> notifier, required Widget builder(BuildContext context, T value, Widget? child), bool buildWhen(T previous, T current)?, void listener(BuildContext context, T value)?, bool listenWhen(T previous, T current)?, Widget? child, bool autoDispose = true}) -
Creates a Reactive widget that rebuilds when
notifierchanges.const -
Reactive.async({Key? key, required AsyncReactiveNotifier<
T> notifier, required Widget data(BuildContext context, T data), Widget loading(BuildContext context)?, Widget error(BuildContext context, Object error, StackTrace? stackTrace)?, Widget initial(BuildContext context)?, bool autoDispose = true}) -
Creates a Reactive widget for AsyncReactiveNotifier with loading/error/data states.
const
-
Reactive.multi({Key? key, required List<
ReactiveNotifier> notifiers, required Widget builder(BuildContext context, Widget? child), Widget? child, bool autoDispose = true}) -
Creates a Reactive widget that rebuilds when any of
notifierschange.const -
Reactive.select({Key? key, required ReactiveNotifier<
T> notifier, required Object? selector(T value), required Widget builder(BuildContext context, Object? selected, Widget? child), Widget? child, bool autoDispose = true}) -
Creates a Reactive widget that only rebuilds when a selected property changes.
const
Properties
- alignBottomCenter → Widget
-
Available on Widget, provided by the AlignmentExtension extension
Aligns the widget to the bottom center of its parent.no setter - alignBottomEnd → Widget
-
Available on Widget, provided by the AlignmentExtension extension
Aligns the widget to the bottom end corner of its parent.no setter - alignBottomStart → Widget
-
Available on Widget, provided by the AlignmentExtension extension
Aligns the widget to the bottom start corner of its parent.no setter - alignCenter → Widget
-
Available on Widget, provided by the AlignmentExtension extension
Aligns the widget to the center of its parent.no setter - alignEndCenter → Widget
-
Available on Widget, provided by the AlignmentExtension extension
Aligns the widget to the start center of its parent.no setter - alignStartCenter → Widget
-
Available on Widget, provided by the AlignmentExtension extension
Aligns the widget to the start center of its parent.no setter - alignTopCenter → Widget
-
Available on Widget, provided by the AlignmentExtension extension
Aligns the widget to the top center of its parent.no setter - alignTopEnd → Widget
-
Available on Widget, provided by the AlignmentExtension extension
Aligns the widget to the top end corner of its parent.no setter - alignTopStart → Widget
-
Available on Widget, provided by the AlignmentExtension extension
Aligns the widget to the top start corner of its parent.no setter - center → Widget
-
Available on Widget, provided by the CenterExtension extension
Wraps the widget with a Center widget.no setter - hashCode → int
-
The hash code for this object.
no setterinherited
- key → Key?
-
Controls how one widget replaces another widget in the tree.
finalinherited
- ltr → Widget
-
Available on Widget, provided by the DirectionalityExtension extension
Wraps the current widget in a Directionality widget with TextDirection.ltr.no setter - rtl → Widget
-
Available on Widget, provided by the DirectionalityExtension extension
Wraps the current widget in a Directionality widget with TextDirection.rtl.no setter - runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
Methods
-
alignedBox(
{double? width, double? height, AlignmentDirectional? alignment}) → Widget -
Available on Widget, provided by the SizedBoxExtension extension
Creates a SizedBox with specified width, height, and alignment. -
animatedOpacity(
bool isVisible, {Duration duration = const Duration(milliseconds: 300)}) → AnimatedOpacity -
Available on Widget, provided by the VisibilityExtension extension
Wraps the widget with an AnimatedOpacity widget to animate its visibility. -
box(
{double? width, double? height}) → Widget -
Available on Widget, provided by the SizedBoxExtension extension
Creates a SizedBox with both width and height. -
createElement(
) → StatefulElement -
Creates a StatefulElement to manage this widget's location in the tree.
inherited
-
createState(
) → State< Reactive< T> > -
Creates the mutable state for this widget at a given location in the tree.
override
-
debugDescribeChildren(
) → List< DiagnosticsNode> -
Returns a list of DiagnosticsNode objects describing this node's
children.
inherited
-
debugFillProperties(
DiagnosticPropertiesBuilder properties) → void -
Add additional properties associated with the node.
inherited
-
expandBox(
) → Widget -
Available on Widget, provided by the SizedBoxExtension extension
Creates a SizedBox that fills the available space in both dimensions. -
expanded(
{int flex = 1}) → Widget -
Available on Widget, provided by the FlexExtensions extension
Wraps the current widget with anExpandedwidget, allowing it to expand and fill available space in a flex container (e.g.,Row,Column). -
flexible(
{int flex = 1, FlexFit fit = FlexFit.loose}) → Widget -
Available on Widget, provided by the FlexExtensions extension
Wraps the current widget with aFlexiblewidget, allowing it to take flexible space within a flex container, but with more control over its layout behavior. -
flexibleBox(
{required double width, double? height}) → Widget -
Available on Widget, provided by the SizedBoxExtension extension
Creates a SizedBox with a flexible width and height. -
height(
double height) → Widget -
Available on Widget, provided by the SizedBoxExtension extension
Creates a SizedBox with a specified height. -
hide(
bool isHidden) → Widget -
Available on Widget, provided by the VisibilityExtension extension
Conditionally hides the widget by replacing it with an empty widget (SizedBox.shrink). -
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
paddedBox(
{double? width, double? height, EdgeInsets? padding}) → Widget -
Available on Widget, provided by the SizedBoxExtension extension
Creates a SizedBox with padding around the child widget. -
paddingAll(
double value) → Widget -
Available on Widget, provided by the PaddingExtension extension
Wraps the widget with a Padding widget applying uniform padding on all sides. -
paddingOnly(
{double top = 0, double bottom = 0, double start = 0, double end = 0}) → Widget -
Available on Widget, provided by the PaddingExtension extension
Wraps the widget with a Padding widget using the specified EdgeInsets. -
paddingSymmetric(
{double vertical = 0, double horizontal = 0}) → Widget -
Available on Widget, provided by the PaddingExtension extension
Wraps the widget with a Padding widget applying symmetric padding. -
positioned(
{double? top, double? bottom, double? start, double? end, double? width, double? height}) → Widget -
Available on Widget, provided by the PositionedExtension extension
Wraps the widget with a PositionedDirectional widget. -
positionedDirectional(
{required TextDirection textDirection, double? top, double? bottom, double? start, double? end, double? width, double? height}) → Widget -
Available on Widget, provided by the PositionedExtension extension
Wraps the widget with a Positioned.directional widget. -
positionedFill(
{double? top, double? bottom, double? left, double? right}) → Widget -
Available on Widget, provided by the PositionedExtension extension
Wraps the widget with a Positioned.fill widget. -
toDiagnosticsNode(
{String? name, DiagnosticsTreeStyle? style}) → DiagnosticsNode -
Returns a debug representation of the object that is used by debugging
tools and by DiagnosticsNode.toStringDeep.
inherited
-
toString(
{DiagnosticLevel minLevel = DiagnosticLevel.info}) → String -
A string representation of this object.
inherited
-
toStringDeep(
{String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug, int wrapWidth = 65}) → String -
Returns a string representation of this node and its descendants.
inherited
-
toStringShallow(
{String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) → String -
Returns a one-line detailed description of the object.
inherited
-
toStringShort(
) → String -
A short, textual description of this widget.
inherited
-
visible(
bool isVisible) → Widget -
Available on Widget, provided by the VisibilityExtension extension
Wraps the widget with a Visibility widget to conditionally show or hide it. -
width(
double width) → Widget -
Available on Widget, provided by the SizedBoxExtension extension
Creates a SizedBox with a specified width.
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited