Search code examples
flutterdartriverpod

Flutter/Riverpod creating copy of complex object with changing value somewhere deep


fellow coders. I am learning Riverpod state management rn. In the documentation, author of the Riverpod suggest to use immutability as much as possible. So i guess to manage state of some complex object I have to create copy of state instance. I have some snadbox project to test functions of Riverpod. There is complex Object called Menu(for restaurant) (see code bellow). And I have no clue how to emit new state with some change somewhere deep in it.

using freezed and fast_immutable_collections (for IList), is it right?

@freezed
class Menu with _$Menu {
  const factory Menu({
    required String? currency,
    required WeeklyMenu? weeklyMenu,
    required StaticMenu? staticMenu,
  }) = _Menu;

  factory Menu.fromJson(Map<String, Object?> json) =>
      _$MenuFromJson(json);
}

@freezed
class WeeklyMenu with _$WeeklyMenu {
  const factory WeeklyMenu({
    required IList<Day>? dayList,
  }) = _WeeklyMenu;

  factory WeeklyMenu.fromJson(Map<String, Object?> json) =>
      _$WeeklyMenuFromJson(json);
}

@freezed
class StaticMenu with _$StaticMenu {
  const factory StaticMenu({
    required IList<MealGroup>? mealGroupList,
    required IList<DrinkGroup>? drinkGroupList,
  }) = _StaticMenu;

  factory StaticMenu.fromJson(Map<String, Object?> json) =>
      _$StaticMenuFromJson(json);
}

@freezed
class Day with _$Day {
  const factory Day({
    required String? id,
    required IList<Meal>? mealList,
    required bool? isChecked,
  }) = _Day;

  factory Day.fromJson(Map<String, Object?> json) => _$DayFromJson(json);
}


@freezed
class MealGroup with _$MealGroup {
  const factory MealGroup({
    required String? id,
    required String? description,
    required String? note,
    required IList<Meal>? mealList,
    required bool? isChecked,
  }) = _MealGroup;

  factory MealGroup.fromJson(Map<String, Object?> json) =>
      _$MealGroupFromJson(json);
}

@freezed
class DrinkGroup with _$DrinkGroup {
  const factory DrinkGroup({
    required String? id,
    required String? description,
    required String? note,
    required IList<Drink>? drinkList,
    required bool? isChecked,
  }) = _DrinkGroup;

  factory DrinkGroup.fromJson(Map<String, Object?> json) =>
      _$DrinkGroupFromJson(json);
}

@freezed
class Meal with _$Meal {
  const factory Meal({
    required String? id,
    required String? name,
    required String? price,
  }) = _Meal;

  factory Meal.fromJson(Map<String, Object?> json) => _$MealFromJson(json);
}


@freezed
class Drink with _$Drink {
  const factory Drink({
    required String? id,
    required String? name,
    required String? price,
  }) = _Drink;

  factory Drink.fromJson(Map<String, Object?> json) => _$DrinkFromJson(json);
}

There is class Menu with subclass StaticMenu (permanent offer of meal) in here is list of MealGroup (4ex. pork, pasta, vegan,...) and each group has unique id, and also contains list of class Meal aslo with unique id. Now a want to create methods, that emits new state but with added/updated/deleted Meal from down bellow, but i guess I have lack of knowledge of the syntax and I have no clue how to write it down.


@riverpod
class MenuNotifier extends _$MenuNotifier {
  @override
  Menu build() {
    return const Menu(
      currency: 'Kč',
      staticMenu: null,
      weeklyMenu: null,
    );
  }

  void initializeMenu() async {
    final menu = await ServerHelper.initializeLocalJson();
    state = menu;
  }

  Future<void> updateOnServer() async {
    ServerHelper.sendMenuToServer(state);
  }

  void updateMealInMealGroup({
    required String mealGroupUid,
    required String mealUid,
    required Meal meal,
  }) {
    //state = state.copyWith(staticMenu: state.staticMenu?.mealGroupList);
  }

  void addMealToMealGroup({
    required String mealGroupUid,
    required String mealUid,
    required Meal meal,
  }) {  }

  void deleteMealinMealGroup({
    required String mealGroupUid,
    required String mealUid,
  }) {  }
}

thank you for any help :)


Solution

  • If you are guided by the item Freezed: Going further: Deep copy, then in general there should be no problem. Everything is extremely immutable :)