RiverPod Maintaining selected item of list

Viewed 400

I am new to riverpod and trying to figure out a state management issue.

I have one list, and two independent states which need access to the list. The states also need to select an element of the list and know what its index is. The list can totally change (add or remove elements) and the states need to determine if their selected element is still in the list and update the index accordingly (to 0 if it is not found)

Here is an example with Riverpod in pure dart:

import 'package:riverpod/riverpod.dart';

void main(List<String> arguments) {
  final container = ProviderContainer();
  List<String> names = ["Jack", "Adam", "Sally"];
  container.read(nameListProvider.notifier).setNames(names);
  //selectedName1 = "Adam"
  //selectedIndex1 = 1
  //selectedName2 = "Sally"
  //selectedIndex2 = 2
  names.remove('Adam');
  container.read(nameListProvider.notifier).setNames(names);
  // print(selectedName1) = "Jack" // set to 0 because selection was removed
  // print(selectedIndex1) = 0
  // print(selectedName2) = "Sally"
  // print(selectedIndex2) = 1 // decrement to match Sally's new list index
}

final nameListProvider =
    StateNotifierProvider<NameListNotifier, List<String>>((ref) {
  return NameListNotifier();
});

class NameListNotifier extends StateNotifier<List<String>> {
  NameListNotifier() : super([]);

  setNames(List<String> names) {
    state = names;
  }
}

But I need the selected Name and Index to be Providers

Update: Here is my more elegant solution:

import 'package:riverpod/riverpod.dart';

void main(List<String> arguments) {
  final container = ProviderContainer();
  List<String> names = ["Jack", "Adam", "Sally"];
  print(container.read(nameListProvider));
  container.read(nameListProvider.notifier).setNames(names);
  var first = container.read(selectionProvider(1).notifier);
  first.setName(1);
  print(container.read(selectionProvider(1)).name);
  var second = container.read(selectionProvider(2).notifier);
  second.setName(2);
  print(container.read(selectionProvider(2)).name);
  names.remove('Adam');
  List<String> newNames = List.from(names);
  container.read(nameListProvider.notifier).setNames(newNames);
  print(container.read(selectionProvider(1)).name);
  print(container.read(selectionProvider(1)).index);
  print(container.read(selectionProvider(2)).name);
  print(container.read(selectionProvider(2)).index);
  print(container.read(nameListProvider));
}


final selectionProvider =
    StateNotifierProvider.family<SelectionNotifier, Selection, int>(
        (ref, page) {
  return SelectionNotifier(ref.read);
});

class SelectionNotifier extends StateNotifier<Selection> {
  Reader _read;
  SelectionNotifier(this._read) : super(Selection());
  update() {
    final String? selectedName = state.name;
    final List<String> names = _read(nameListProvider);
    if (names == []) {
      state = Selection();
      return null;
    }
    if (selectedName == null) {
      state = Selection(name: names[0], index: 0);
      return;
    }
    int i = names.indexOf(selectedName);
    if (i == -1) {
      state = Selection(name: names[0], index: 0);
      return;
    }
    state = Selection(name: selectedName, index: i);
    return;
  }

  setName(int index) {
    final List<String> names = _read(nameListProvider);
    state = Selection(name: names[index], index: index);
  }
}

final nameListProvider =
    StateNotifierProvider<NameListNotifier, List<String>>((ref) {
  return NameListNotifier(ref.read);
});

class NameListNotifier extends StateNotifier<List<String>> {
  Reader _read;
  NameListNotifier(this._read) : super([]);

  setNames(List<String> names) {
    state = names;
    _read(selectionProvider(0).notifier).update();
    _read(selectionProvider(1).notifier).update();
  }
}

class Selection {
  final String? name;
  final int? index;
  Selection({this.name, this.index});
}
0 Answers
Related