I tried out the flutter_bloc package but I run into this error:
The following assertion was thrown building BlocBuilder<MyCubit, MyState>(dirty, dependencies: [_InheritedProviderScope<MyCubit?>], state: _BlocBuilderBaseState<MyCubit, MyState>#8c21a):
setState() or markNeedsBuild() called during build.
This Form widget cannot be marked as needing to build because the framework is already in the process of building widgets. A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was: Form-[LabeledGlobalKey<FormState>#24535]
state: FormState#05273
The widget which was currently being built when the offending call was made was: BlocBuilder<MyCubit, MyState>
dirty
dependencies: [_InheritedProviderScope<MyCubit?>]
state: _BlocBuilderBaseState<MyCubit, MyState>#8c21a
The relevant error-causing widget was:
BlocBuilder<MyCubit, MyState> BlocBuilder:file:///E:/Projekte/untitled9/lib/main.dart:47:18
Here is my code:
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'my_cubit.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return BlocProvider<MyCubit>(
create: (context) => MyCubit(),
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(),
),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Flutter Demo Home Page'),
),
body: Form(
key: formKey,
child: Center(
child: BlocBuilder<MyCubit, MyState>(
builder: (context, state) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextFormField(
initialValue: state.text,
onChanged: (value) {
if (!formKey.currentState!.validate()) {
return;
}
final newData = state.copyWith(text: value);
BlocProvider.of<MyCubit>(context).changeData(newData);
},
validator: (v) => v!.trim().isNotEmpty ? null : 'error',
),
ElevatedButton(
onPressed: formKey.currentState == null || !formKey.currentState!.validate() ? null : () { // this causes the error
print('hi');
},
child: const Text('Press'),
),
],
);
},
),
),
),
);
}
}
I know that the error is caused the by the conditional onPressed property of my ElevatedButton. If I replace the line onPressed: formKey.currentState == null || !formKey.currentState!.validate() ? null : () { with the simple onPressed: () { everything works fine. But I want to disable or enable the button based on the current user input and if it is valid.
What is the default why to fix this? Should the BLoC handle the validation?