The ReactiveViewModelBuilder
was created to provide a more intuitive and efficient way to handle ViewModel states while maintaining the simplicity and power of ReactiveNotifier.
Key Features and Benefits
1. Type-Safety and Clear Intent
When using ReactiveViewModelBuilder
, it's recommended to use the data type managed by the ViewModel rather than the ViewModel itself. For example:
// Recommended ✅
ReactiveViewModelBuilder<ProductData>(
notifier: productStateNotifier.notifier,
builder: (state, keep) => ProductView(data: state)
)
// Not recommended ❌
ReactiveViewModelBuilder<ProductViewModel>
2. Practical Example
Here's a typical use case:
// ProductViewModel
class ProductViewModel extends ViewModelStateImpl<ProductData> {
ProductViewModel() : super(ProductData());
void updatePrice(double newPrice) {
updateState(data.copyWith(price: newPrice));
}
void updateStock(int newStock) {
updateState(data.copyWith(stock: newStock));
}
}
// Usage in UI
ReactiveViewModelBuilder<ProductData>(
notifier: productStateNotifier.notifier,
builder: (state, keep) {
return Column(
children: [
Text('Price: ${state.price}'),
Text('Stock: ${state.stock}'),
ElevatedButton(
onPressed: () {
// Access ViewModel methods through notifier
productStateNotifier.notifier.updatePrice(99.99);
},
child: Text('Update Price'),
),
],
);
},
)
Clear Separation of Concerns
- State Access: Through the
state
parameter in the builder - ViewModel Actions: Through
notifier
methods - State Updates: Handled automatically without manual transforms
Alternative Approaches
If not using ReactiveViewModelBuilder
, state updates in ViewModels require manual transformation:
// Without ReactiveViewModelBuilder
myStateNotifier.transformState((s) => s); // Required after ViewModel updates
Recommendations for Different Use Cases
Use ReactiveViewModelBuilder when:
- Working with complex ViewModels
- Handling nested state updates
- Need clear separation between state and actions
- Managing form states or complex UI states
Example:
class OrderViewModel extends ViewModelStateImpl<OrderData> {
void updateOrderStatus(OrderStatus status) {
updateState(data.copyWith(status: status));
}
}
// In UI
ReactiveViewModelBuilder<OrderData>(
notifier: orderStateNotifier.notifier,
builder: (state, keep) {
return OrderStatusWidget(
status: state.status,
onStatusChange: (newStatus) {
orderStateNotifier.notifier.updateOrderStatus(newStatus);
},
);
},
)
Use ReactiveBuilder when:
- Working with simple states
- Managing model states with copyWith
- Need direct state transformations
- Handling single-value states
Example:
// Simple user model state
final userStateNotifier = ReactiveNotifier(() => User());
ReactiveBuilder(
notifier: userStateNotifier,
builder: (user, keep) {
return UserProfileCard(user: user);
},
)
Performance Benefits
- Optimized for ViewModel state updates
- Prevents unnecessary rebuilds
- Efficient handling of nested state changes
- Built-in debouncing for rapid updates
Although technically I could have created a named class, I preferred to duplicate a bit of the code, to reduce the coupling and overhead of ReactiveBuilder, this also allows me to freely modify in case of any problems of the 2 and to have a clear separation, it also makes contributions easier.
Sometimes a little bit of repeated code saves lives, 😀.
It should be noted that we are still in the stage of standardizing behavior, so code quality and optimization are not a priority at the moment.
Any suggestions or contributions are welcome.
With ❤️ from Jhonacode.