Hi, I have a problem regarding the BlocProvider.of(context) method.
I created a small test app with the following main.dart file
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:bloc/bloc.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: TestWidget(),
);
}
}
class TestWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider<TestBloc>(
builder: (BuildContext context) => TestBloc(),
child: Scaffold(
appBar: AppBar(
title: Text('Test'),
actions: <Widget>[
IconButton(
icon: Icon(Icons.add_circle_outline),
onPressed: () {
BlocProvider.of<TestBloc>(context).add(TestEvent.event2);
},
)
],
),
),
);
}
}
enum TestEvent {
event1,
event2
}
enum TestState {
state1,
state2
}
class TestBloc extends Bloc<TestEvent, TestState> {
@override
TestState get initialState => TestState.state1;
@override
Stream<TestState> mapEventToState(TestEvent event) async* {
if (event == TestEvent.event1) {
yield TestState.state1;
} else {
yield TestState.state2;
}
}
}
When clicking the button, the following error is thrown:
No ancestor could be found starting from the context that was passed to BlocProvider.of<TestBloc>().
This can happen if:
1. The context you used comes from a widget above the BlocProvider.
2. You used MultiBlocProvider and didn't explicity provide the BlocProvider types.
Good: BlocProvider<TestBloc>(builder: (context) => TestBloc())
Bad: BlocProvider(builder: (context) => TestBloc()).
The context used was: TestWidget
When the exception was thrown, this was the stack
#0 BlocProvider.of
package:flutter_bloc/src/bloc_provider.dart:80
#1 TestWidget.build.<anonymous closure>
package:flutter_bloc_issue/main.dart:28
#2 _InkResponseState._handleTap
package:flutter/β¦/material/ink_well.dart:654
#3 _InkResponseState.build.<anonymous closure>
package:flutter/β¦/material/ink_well.dart:729
#4 GestureRecognizer.invokeCallback
package:flutter/β¦/gestures/recognizer.dart:182
...
Handler: "onTap"
Recognizer: TapGestureRecognizer#02b38
debugOwner: GestureDetector
state: possible
won arena
finalPosition: Offset(391.7, 72.3)
finalLocalPosition: Offset(25.7, 28.3)
sent tap down
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Am I doing something wrong?
Thanks in advance for your help!
Hi @hoi4 π
Thanks for opening an issue!
The problem is youβre trying to access BlocProvider from the same context in which it was instantiated. I would recommend wrapping TestWidget in the BlocProvider instead.
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:bloc/bloc.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: BlocProvider<TestBloc>(
builder: (context) => TestBloc(),
child: TestWidget(),
);
}
}
class TestWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Test'),
actions: <Widget>[
IconButton(
icon: Icon(Icons.add_circle_outline),
onPressed: () => BlocProvider.of<TestBloc>(context).add(TestEvent.event2),
),
],
),
);
}
}
Hope that helps π
Most helpful comment
Hi @hoi4 π
Thanks for opening an issue!
The problem is youβre trying to access BlocProvider from the same context in which it was instantiated. I would recommend wrapping TestWidget in the BlocProvider instead.
Hope that helps π