Difference between List.add and manually adding item to a Riverpod StateNotifier<List<String>>

720

The state must change in a way that oldValue == newValue is false. And by default, adding elements to a list with .add mutates the list in place, so equality is preserved. That's why's all the examples have something like state = [...state, foo], so that an entirely new list is in state, and that's not equal to the old list.

Share:
720
Giorgio
Author by

Giorgio

Computer scientist

Updated on December 26, 2022

Comments

  • Giorgio
    Giorgio over 1 year

    I'd like to learn how to use Riverpod, so to this end I'm implementing a small app that shows a list of items and a button that adds a dummy item to the list when tapped.

    Problem context

    Pressing the button in the following app works as expected (a dummy item is added, and the change is immediately reflected in the UI):

    import 'package:flutter/material.dart';
    import 'package:flutter_riverpod/flutter_riverpod.dart';
    
    
    
    void main() => runApp(const ProviderScope(child: MyApp()));
    
    class MyApp extends StatelessWidget {
      const MyApp({Key key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) => MaterialApp(home: HomePage());
    }
    
    
    
    final itemsProvider = StateNotifierProvider((ref) => ItemsList());
    
    class ItemsList extends StateNotifier<List<String>> {
      ItemsList([List<String> items]) : super(items ?? []);
    
      void add(String item) => state = [...state, item];
    }
    
    
    
    class HomePage extends ConsumerWidget {
      const HomePage({Key key}) : super(key: key);
    
      @override
      Widget build(BuildContext context, ScopedReader watch) {
        final items = watch(itemsProvider.state);
        return Scaffold(
          body: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: items.map((e) => Text(e)).toList(),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: () => context.read(itemsProvider).add('Other item'),
            tooltip: 'Add item',
            child: Icon(Icons.add),
          ),
        );
      }
    }
    

    Problem

    Inside the add method of the ItemsList class, I thought that changing the statement state = [...state, item] to state.add(item) would not make any difference. However, doing so makes the app not responsive to state changes anymore: tapping the button doesn't trigger a change to the UI, and I don't see any new item in the UI until I hot-reload my app.

    So just to be clear: changing void add(String item) => state = [...state, item]; to void add(String item) => state.add(item); breaks the link between app state and UI.

    Why is manually adding an item with list destructuring different from using List.add? Thank you very much in advance.

  • Amine LAHRIM
    Amine LAHRIM over 2 years
    it's should be something like .refresh() in case there is a very big list will copy into next each time is not optimal for performance, hope in future this gets fixed