Skip to content

v2.5.0-release

Latest
Compare
Choose a tag to compare
@JhonaCodes JhonaCodes released this 03 Feb 12:44
33be565

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.