Main question
Hello! In Flutter I am using BLoC, and more specifically cubits, to manage the state of my app.
I have a few states in my weather_state.dart
file:
- WeatherInitial
- WeatherLoading
- WeatherLoaded
- WeatherError
For the latter, I would like to pass an error message when the state is emitted, as you can see in this method, from weather_cubit.dart
(last line):
Future<void> getWeather(String cityName) async {
emit(const WeatherLoading());
try {
final weather = await _weatherRepository.fetchWeather(cityName);
emit(WeatherLoaded(weather));
} on NetworkException {
emit(const WeatherError('Error fetching the data.'));
}
}
Now, I just localized my app, and therefore wanted to localize the error message as well. I imported the necessary packages in my cubit, and then accessed the localized error message that way:
emit(WeatherError(AppLocalizations.of(context)!.errorFetchingData));
I get the following error: Undefined name 'context'.
.
I understand why, obviously, but my question then is:
How do I access the context from inside a cubit?
And if there are multiple ways, what is the most optimized one to do so?
PS: If you have a decent workaround, feel free to mention it, too.
What I found:
Apparently, from this ressource, I found that providing the context that way (here, in my home_screen.dart
):
return BlocProvider<WeatherCubit>(
create: (context) => WeatherCubit(),
child: MaterialApp(
...was supposed to make it accessible in my cubit. It does not work for me, as you can guess. By the way, I am searching for something a bit better than providing the context as a parameter in the cubit constructor (because that would be a real pain for testing afterwards).
Edit
I know I can pass an error message as a String parameter in my method. I also already use an error message property in my WeatherError state.
My problem is that the error message depends on the behavior of the method itself, which does not make possible passing an argument inside.
I took a simple example before, but I will provide another one there:
Suppose I have a UUID that I'm getting from a QR code scan.
I am passing the UUID as a parameter of the selectCity method:
void selectCity(String? cityUuid) async {
const uuidPattern =
r'[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}';
final regexUuid = RegExp(uuidPattern);
if (cityUuid == null) {
emit(CitySelectionError('The QR code scanner had an error. Please try again.'));
} else if (!regexUuid.hasMatch(cityUuid)) {
emit(CitySelectionError('The QR code does not contain a UUID and cannot match a city.'));
} else {
emit(CitySelected(cityUuid));
}
}
The error state:
class CitySelectionError extends CityState {
final String errorMessage;
CitySelectionError(this.errorMessage) : super(null);
// Equatable: don't mind
@override
List<Object?> get props => [errorMessage];
}
I first want to check if it is null, as this would be a result of scanning failure, before checking if the string is an actual UUID.
As you can see, the error messages clearly depend on the method implementation. This implies that I cannot pass the error messages as parameters; this would not make any sense.
Any idea about what I am missing?