Reputation: 2270
In the following snippet the state.copyWith function is not available.
@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);
}
}
However when I remove the sealed classes the copyWith function is available.
@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);
}
}
What do I need to change to make the copyWith available in the first snippet?
Upvotes: 3
Views: 6701
Reputation: 13690
Only properties that are common to all constructors will generate a copyWith
method, as mentioned in the README docs.
We can use copyWith with properties defined on all constructors...
Imagine you had an instance of Loading
, what copyWith
method would you expect that to have? It has no properties, hence it can't have any copyWith
methods, therefore the union of all types also can't.
However, you can use pattern matching to call copyWith
on the instances of the right type.
In your example, something like this would work:
MyState myState = ...;
myState.maybeMap(
initial: (v: Initial) => v.copyWith(counter: v.counter + 1),
orElse: () => ...,
);
Or using when
:
MyState myState = ...;
myState.when(
(int counter) => MyState.initial(counter + 1),
loading: () => loading,
one: () => one,
two: () => two,
);
Upvotes: 11
Reputation: 471
you can access the copyWith method, do Type conversion:
`if (state is CurrentState) { final myState = state as CurrentState }
myState.copyWith (...)`
Upvotes: 4