ReactiveStatelessWidget constructor
const
ReactiveStatelessWidget({
- Key? key,
Use it instead of StatelessWidget to make the hole sub tree reactive.
Any state consumed in any widget child of the widget where the ReactiveStatelessWidget will be registered.
The list of registered states are updated for each rebuild. And any non used state will be removed from the list of subscribers.
Example:
@immutable
class ViewModel {
// Inject a reactive state of type int.
// Works for all primitives, List, Map and Set
final counter1 = 0.inj();
// For non primitives and for more options
final counter2 = RM.inject<Counter>(
() => Counter(0),
// State will be redone and undone
undoStackLength: 8,
// Build-in logger
debugPrintWhenNotifiedPreMessage: 'counter2',
);
//A getter that uses the state of the injected counters
int get sum => counter1.state + counter2.state.value;
incrementCounter1() {
counter1.state++;
}
incrementCounter2() {
counter2.state = Counter(counter2.state.value + 1);
}
}
class CounterApp extends ReactiveStatelessWidget {
const CounterApp();
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Counter1View(),
Counter2View(),
Text('🏁 Result: ${viewModel.sum}'), // Will be updated when sum changes
],
);
}
}
// Child 1 - Plain StatelessWidget
class Counter1View extends StatelessWidget {
const Counter1View({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Column(
children: [
ElevatedButton(
child: const Text('🏎️ Counter1 ++'),
onPressed: () => viewModel.incrementCounter1(),
),
// Listen to the state from parent
Text('Counter1 value: ${viewModel.counter1.state}'),
],
);
}
}
// Child 2 - Plain StatelessWidget
class Counter2View extends StatelessWidget {
const Counter2View({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Column(
children: [
ElevatedButton(
child: const Text('🏎️ Counter2 ++'),
onPressed: () => viewModel.incrementCounter2(),
),
ElevatedButton(
child: const Text('⏱️ Undo'),
onPressed: () => viewModel.counter2.undoState(),
),
Text('Counter2 value: ${viewModel.counter2.state.value}'),
],
);
}
}
Important Notes:
- Child widgets that are load lazily can not register state to the parent
ReactiveStateless
. For example:- The Widgets rendered inside the builder method of ListView.builder.
- Widgets rendered inside SliverAppBar, SliverList and SliverGrid.
- Never use ReactiveStatelessWidget above MaterialApp. See TopStatelessWidget
ReactiveStatelessWidget offers the following hooks: ReactiveStatelessWidget.didMountWidget, ReactiveStatelessWidget.didUnmountWidget ReactiveStatelessWidget.didAddObserverForDebug ReactiveStatelessWidget.shouldRebuildWidget
didNotifyWidget
Implementation
const ReactiveStatelessWidget({Key? key}) : super(key: key);