skip to Main Content

I’m new to riverpod and trying to make a shopping cart with it.

final cartProvider = StateProvider<List<CartItem>>((ref) {
  return <CartItem>[];
});

// onPressed callback
addToCart(Product prod, WidgetRef ref) {
  CartItem item = CartItem(count: 1, product: prod);

  ref.read(cartProvider.notifier).state.add(item);

  // ignore: avoid_print
  print("product added ${prod.title}");
}
 

Then I added some products and went to cart page and products were there.

Then I tried this:

final cartProvider = Provider<List<CartItem>>((ref) {
  return <CartItem>[];
});

// onPressed callback
addToCart(Product prod, WidgetRef ref) {
  CartItem item = CartItem(count: 1, product: prod);

  ref.read(cartProvider).add(item);

  // ignore: avoid_print
  print("product added ${prod.title}");
}

Then I tested it. It works too.
Based on the docs, Provider exposes a read-only value so this shouldn’t work right? What am I missing? What’s the difference between this two?

Info: I’m using a ConsumerWidget for both products page and cart page.
In the cart page I have:

....
@override
Widget build(BuildContext context, WidgetRef ref) {
    WidgetRef refx = ref;
    List<CartItem> lst = refx.watch(cartProvider);
....
}

2

Answers


  1. One of the best and suggested way by lot of experience riverpod developer is below

    addToCart(Product prod, WidgetRef ref) {
      CartItem item = CartItem(count: 1, product: prod);
    
      // ref.read(cartProvider).add(item);
      ref.read(cartProvider.notifier).update((state) => [...state, item]);
    
      print("product added ${prod.title}");
    }
    
    Login or Signup to reply.
  2. Technically, you can do as you please. However, your state is a complex object, not a primitive type, and so in order for the provider to actually update, you need to use the List.of(...) method or the spread operator:

    addToCart(Product prod, WidgetRef ref) {
      CartItem item = CartItem(count: 1, product: prod);
    
      final state = ref.read(cartProvider.notifier);
    
    
      state.add(item);
      ref.read(cartProvider.notifier).state = List.of(state);
    
      // or
      ref.read(cartProvider.notifier).update((state) => [...state, item]);
      
    
    }
    

    This behavior applies to all non-immutable objects, such as collections. If your object is simple, then you can do a normal assignment.

    The ref.read(provider.notifier).update method exists rather to allow you to update your state based on the old state. It’s just syntactic sugar.

    In any other case, your provider will not be updated and the widget will not be rebuilt with the new data. Because the rebuild relies on a simple updateShouldNotify method:

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search