【问题标题】:@freezed copyWith missing with sealed classes@freezed copyWith 缺少密封类
【发布时间】:2021-08-23 04:00:48
【问题描述】:

在下面的sn-p中,state.copyWith函数不可用。

@freezed
class MyState with _$MyState {
  @JsonSerializable(fieldRename: FieldRename.snake, explicitToJson: true)
  const factory MyState({@Default(0) int counter,}) = _MyState;
  const factory MyState.initial({@Default(0) int counter}) = Initial;
  const factory MyState.loading() = Loading;
  const factory MyState.one() = One;
  const factory MyState.two() = Two;

  factory MyState.fromJson(Map<String, dynamic> json) =>
      _$MyStateFromJson(json);
}

class MyStateNotifier extends StateNotifier<MyState> {
  MyStateNotifier() : super(MyState.initial());

  Future<void> one() async {
    state = MyState.loading();
    await Future.delayed(Duration(seconds: 5));
    state.copyWith(counter: 1);
  }
}

但是,当我删除密封类时,copyWith 函数可用。

@freezed
class MyState with _$MyState {
  @JsonSerializable(fieldRename: FieldRename.snake, explicitToJson: true)
  const factory MyState({@Default(0) int counter,}) = _MyState;
  // const factory MyState.initial({@Default(0) int counter}) = Initial;
  // const factory MyState.loading() = Loading;
  // const factory MyState.one() = One;
  // const factory MyState.two() = Two;

  factory MyState.fromJson(Map<String, dynamic> json) =>
      _$MyStateFromJson(json);
}

class MyStateNotifier extends StateNotifier<MyState> {
  MyStateNotifier() : super(MyState());

  Future<void> one() async {
    await Future.delayed(Duration(seconds: 5));
    state.copyWith(counter: 1);
  }
}

我需要进行哪些更改才能使 copyWith 在第一个 sn-p 中可用?

【问题讨论】:

    标签: flutter dart flutter-freezed


    【解决方案1】:

    只有所有构造函数共有的属性才会生成copyWith 方法,如README docs 中所述。

    You also can use copyWith with properties defined on all constructors...
    

    假设你有一个Loading 的实例,你希望它有什么copyWith 方法?它没有属性,因此它不能有任何copyWith 方法,因此所有类型的 union 也不能。

    但是,您可以使用模式匹配在正确类型的实例上调用 copyWith

    在你的例子中,这样的事情会起作用:

    MyState myState = ...;
    
    myState.maybeMap(
        initial: (v: Initial) => v.copyWith(counter: v.counter + 1),
        orElse: () => ...,
    );
    

    或者使用when:

    MyState myState = ...;
    
    myState.when(
        (int counter) => MyState.initial(counter + 1),
        loading: () => loading,
        one: () => one,
        two: () => two,
    );
    

    【讨论】:

    • 将计数器添加到所有构造函数中效果很好。但是,我需要在每次调用时都提供它,因为随着代码的增长而添加的每个属性。这会让工作变得非常痛苦。是否有某种方法可以自动将公共属性从一种状态复制/粘贴到另一种状态?类似state = MyState.loading(copyFromExistingStateAllCommonProperties);
    • 为什么你会在Loading 上有一个counter?这似乎没有意义。
    • 是否可以向MyState 添加一个扩展函数,为任何没有该属性的类型返回0
    • 如果有人有时间stackoverflow.com/questions/69783285/…,请在这里发布一个更具体的问题
    【解决方案2】:

    你可以访问copyWith方法,做类型转换:

    `如果(状态为当前状态){ final myState = 状态为 CurrentState }

    myState.copyWith (...)`

    【讨论】:

      猜你喜欢
      • 2021-11-16
      • 1970-01-01
      • 2021-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多