Bloc: BlocProvider.of() called with a context that does not contain a Bloc of type ...

Created on 4 May 2020  ยท  5Comments  ยท  Source: felangel/bloc

I'm new to Flutter and I'm trying to implement Bloc pattern for my notes app.

So I have to use Bloc in button on AppBar and in NotesView. It works fine in NoteView, but when I added it to the NoteFilterButton, I'm getting the error:

BlocProvider.of() called with a context that does not contain a Bloc of type NotesBloc.
I/flutter ( 6501): No ancestor could be found starting from the context that was passed to
I/flutter ( 6501): BlocProvider.of().
I/flutter ( 6501):
I/flutter ( 6501): This can happen if the context you used comes from a widget above the BlocProvider.
I/flutter ( 6501):
I/flutter ( 6501): The context used was: BlocBuilder(dirty, state:
I/flutter ( 6501): _BlocBuilderBaseState

class NotesPage extends StatelessWidget{
NotesPage();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: [
NoteFilterButton()
],
),
body: BlocProvider(
create: (context) => NotesBloc(notesRepository: FirebaseNotesRepository()),
child: NotesView(),
),
);
}
}

my NoteFilterButton:

`class NoteFilterButton extends StatelessWidget{

@override
Widget build(BuildContext context) {

return BlocBuilder<NotesBloc, NotesState>(
  builder: (context, state){
    return IconButton(
      icon: Icon(Icons.sort),
      onPressed: (){
        showDialog(barrierDismissible: false, context: context,builder: (_) =>
            SortDialog(initialSortOption: state.sortOption, initialOrderOption: state.orderOption,) ).then((res){
          ...
        });
      },
    );
  }
);

}
}`

What am I missing here?

question

Most helpful comment

@RollyPeres Moving BlocProvider over the Scaffold did the trick!

Thanks again for your help, you were very responsive.

All 5 comments

The BlocProvider need to be in parent widget of NoteFilterButton(), try to change it at Scaffold

BlocProvider(
create: (context) => NotesBloc(notesRepository: FirebaseNotesRepository()),
child: Scaffold(),)

Hi @YanaKrivitskaya ! ๐Ÿ‘‹

In your setup BlocProvider is below your button so you won't have access to it.
Consider lifting up your BlocProvider above Scaffold.

If you're only needing NotesBloc in your dialog then consider removing the BlocBuilder and passing your bloc like so:

return IconButton(
      icon: Icon(Icons.sort),
      onPressed: (){
        showDialog(barrierDismissible: false, context: context,builder: (_) =>
            BlocProvider.value(value: context.bloc<NotesBloc>(), child: SortDialog())).then((res){
          ...
        });
      },
    );

This way you won't need to pass all those parameters and just consume your bloc state in your SortDialog using BlocBuilder, BlocListener, BlocConsumer or even just context.bloc<NotesBloc>().state if you just need to grab the current state of the bloc.

Hope that helps you ๐Ÿ‘

@RollyPeres Thank you for your answer!

Maybe it's a stupid question, but it's not obvious to me how to get state in Sort Dialog.

So I've updated it to :

`showDialog(barrierDismissible: false, context: context,builder: (_) =>
BlocProvider.value(
value: context.bloc(),
child: SortDialog())
).then((res){

    });`

And In my Sort Dialog I'm trying to use BlocBuilder:

`class SortDialog extends StatefulWidget {
NotesBloc _notesBloc;

@override
_SortDialogState createState() => new _SortDialogState();
}

class _SortDialogState extends State{
NotesBloc _notesBloc;

@override
void initState() {
super.initState();
_notesBloc = BlocProvider.of(context);
}

@override
Widget build(BuildContext context){

return BlocBuilder<NotesBloc, NotesState>(
    builder: (context, state){
      print(state.sortOption);
      return new AlertDialog(
        title: Text('Sort by'),
        actions: <Widget>[
          FlatButton(
            child: Text('Done'),
            onPressed: () {Navigator.pop(context, new SortOrder(_selectedSortOption, _selectedOrderOption));},
          ),
          FlatButton(
            child: Text('Cancel'),
            onPressed: () {Navigator.pop(context);},
          ),
        ],
        content: SingleChildScrollView(
          child: Column(
            children: <Widget>[
              _sortOptions(),
              Divider(color: ColorsPalette.blueHorizon),
              _orderOptions()
            ],
          ),
        ),
      );
    }
);

}`

Still getting error

BlocProvider.of() called with a context that does not contain a Bloc of type NotesBloc.
I/flutter ( 6501): No ancestor could be found starting from the context that was passed to
I/flutter ( 6501): BlocProvider.of().
I/flutter ( 6501):

No worries @YanaKrivitskaya , there's no such thing as stupid question in dev world โœŒ

Please be explicit with type when using BlocProvider.value e.g.: value: context.bloc<NotesBloc>(),

Your SortDialog widget can be Stateless unless you have some additional state to keep track of.
You can simply use BlocBuilder like you already do, without the need to manually retrieve the bloc in initState since BlocBuilder will do just that for you.

Don't forget to move your initial BlocProvider on top of Scaffold ๐Ÿคž

Hope that gets you on the right track! ๐ŸŽ‰

@RollyPeres Moving BlocProvider over the Scaffold did the trick!

Thanks again for your help, you were very responsive.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

MahdiPishguy picture MahdiPishguy  ยท  3Comments

RobPFarley picture RobPFarley  ยท  3Comments

frankrod picture frankrod  ยท  3Comments

abinvp picture abinvp  ยท  3Comments

nhwilly picture nhwilly  ยท  3Comments