Flutter Bloc : No ancestor could be found starting from the context?
The line below is your problem. The error is exactly what the message says.
...
child: BlocBuilder<BtnEvent, BtnState>(
bloc: BlocProvider.of<BtnBloc>(context), <------- Problem line
builder: (context, BtnState state) {
...
The context you're using there does not have a BlocBuilder attached to it so nothing is passing the BloC down from the top to your LoginState. You can either
- Use your existing bloc (_btnBloc) and pass it in (recommended)
- Wrap the widget putting the LoginState on screen with a BlocProvider so that you have access to it in the widget state.
If this is your first view then use 1.
Change
bloc: BlocProvider.of<BtnBloc>(context), <------- Problem line
To
bloc: _btnBloc
After the while of time facing this problem, I hope this article will help you to understand more about context
.
The general solution is the same as the @Filled Stacks's answer. It means that you have to pass the bloc when navigating into a new page, so the BlocProvider
can find which type of Bloc you will be received.
I recommend initing the main function for the overall application which will init your screens and context through the screens. For eg:
- Init and passing Bloc:
class ListTodoPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider<TodoBloc>(
create: (context) => TodoBloc(TodoDao())..add(QueryTodoEvent()),
child: ListTodoPageful());
}
}
class ListTodoPageful extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return ListTodoState();
}
}
class ListTodoState extends State<ListTodoPageful> {
TodoBloc _todoBloc;
@override
Widget build(BuildContext context) {
_todoBloc = BlocProvider.of<TodoBloc>(
context);
//...
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.push(
context,
CupertinoPageRoute(
builder: (context) => BlocProvider.value(
value: _todoBloc, child: CreateTaskPage())));
}
//...
}
- Receive Bloc:
class _CreatePageState extends State<CreateTaskPage> {
TodoBloc _todoBloc;
@override
Widget build(BuildContext context) {
_todoBloc = BlocProvider.of<TodoBloc>(context);
}
Refer to my sample application here: https://github.com/huynguyennovem/flutter_todo