I am creating a cubit. However, after running the build_runner
command, the copyWith()
method is not being generated.
My search_cubit.dart
file:
import 'package:book_ai/domain/book/book.dart';
import 'package:book_ai/domain/book/i_book_repository.dart';
import 'package:book_ai/domain/search/search_failure.dart';
import 'package:book_ai/domain/search/value_objects.dart';
import 'package:dartz/dartz.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:injectable/injectable.dart';
part 'search_cubit.freezed.dart';
part 'search_state.dart';
@injectable
class SearchCubit extends Cubit<SearchState> {
final IBookRepository _bookRepository;
SearchCubit(this._bookRepository) : super(SearchState.initial());
void updateSearchQuery(String typedQuery) {
emit(state.copyWith(
searchQuery: SearchQuery(typedQuery),
searchFailureOrSuccessOption: none(),
));
}
Future<void> search() async {
emit(state.copyWith(isSubmitting: true));
final possibleFailure =
await _bookRepository.get(state.searchQuery.getOrCrash());
emit(possibleFailure.fold(
(failure) {
failure.maybeWhen(
unexpected: () => emit(
state.copyWith(
isSubmitting: false,
searchFailureOrSuccessOption: some(
left(
const SearchFailure.otherFailure('unknown'),
),
),
),
),
orElse: () => const SearchFailure.serverError());
},
(books) => SearchState.searchSuccess(books),
));
// emit(state.copyWith(
// isSubmitting: false,
// searchFailureOrSuccessOption: optionOf(result),
// ));
}
}
My search_state.dart
file:
part of 'search_cubit.dart';
@freezed
class SearchState with _$SearchState {
const factory SearchState({
required SearchQuery searchQuery,
required bool isSubmitting,
required Option<Either<SearchFailure, Unit>> searchFailureOrSuccessOption,
}) = _SearchState;
const SearchState._();
const factory SearchState.initial() = _Initial;
const factory SearchState.loading() = _Loading;
const factory SearchState.searchFailure(SearchFailure failure) =
_SearchFailure;
const factory SearchState.searchSuccess(List<Book> books) = _SearchSuccess;
}
I tried modifying the search_state.dart
file to explicitly define the SearchState.initial()
like this:
factory SearchState.initial() => SearchState(
searchQuery: SearchQuery(''),
isSubmitting: false,
searchFailureOrSuccessOption: none());
while removing the other states. In this case, the copyWith
method works. However, I want to be able to use the other states too.
If you want have multiple states and then to be able use copyWith() you should explicitly cast to state that has params in the constructor.
@freezed
class SearchState with _$SearchState {
const SearchState._();
const factory SearchState.initial() = _Initial;
const factory SearchState.loading() = _Loading;
const factory SearchState.searching({
required SearchQuery searchQuery,
required Option<Either<SearchFailure, Unit>> searchFailureOrSuccessOption,
@Default(false) bool isSubmitting,
}) = Searching;
const factory SearchState.searchFailure(SearchFailure failure) = SearchFailure;
const factory SearchState.searchSuccess(List<Book> books) = SearchSuccess;
}
and then
void updateSearchQuery(String typedQuery) {
if (state is Searching) {
emit(
(state as Searching).copyWith(
searchQuery: SearchQuery(typedQuery),
searchFailureOrSuccessOption: none(),
),
);
}
then in screen:
@override
Widget build(BuildContext context) => BlocBuilder<SearchCubit, SearchState>(
builder: (context, state) => state.when(
initial: () => const SizedBox(),
loading: () => ProgressLoader()
searching: (ages, searchFailureOrSuccessOption, isSubmitting) => Container(..)
...
more info freezed