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

Created on 31 Aug 2019  ยท  29Comments  ยท  Source: felangel/bloc

I had a problem with getting Bloc from child widget and I have no idea what I'm doing wrong.
I'm using flutter_bloc v.0.21.0.

Here is my main.dart:

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

import './pages/splashPage.dart';
import './pages/loginPage.dart';
import './pages/homePage.dart';

import "./blocs/authenticationBloc.dart";

void main() => runApp(WeatherApp());

class WeatherApp extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _WeatherAppState();
}

class _WeatherAppState extends State<WeatherApp> {
  AuthenticationBloc _authenticationBloc;

  @override
  void initState() {
    _authenticationBloc = AuthenticationBloc();
    _authenticationBloc.dispatch(AppStarted());

    super.initState();
  }

  @override
  void dispose() {
    _authenticationBloc.dispose();

    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return BlocProvider<AuthenticationBloc>(
      builder: (context) => _authenticationBloc,
      child: MaterialApp(
        debugShowCheckedModeBanner: true,
        home: BlocBuilder(
          bloc: _authenticationBloc,
          builder: (context, state) {
            if (state is AuthenticationUninitialized) {
              return SplashPage();
            } else if (state is AuthenticationAuthenticated) {
              return HomePage();
            } else if (state is AuthenticationUnauthenticated) {
              return LoginPage();
            }
          },
        ),
      ),
    );
  }
}

And here in LoginPage widget I'm getting my authenticationBloc using BlocProvider.of method (in initState method):

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

import "../blocs//authenticationBloc.dart";

class LoginPage extends StatefulWidget {
  @override
  _LoginPageState createState() => _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {
  AuthenticationBloc _authenticationBloc;

  @override
  void initState() {
    _authenticationBloc = BlocProvider.of<AuthenticationBloc>(context);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('This is login page'),
            RaisedButton(
              child: Text('Login'),
              onPressed: () => {},
            )
          ],
        ),
      ),
    );
  }
}

but instead of receiving bloc I got this error:

flutter: โ•โ•โ•ก EXCEPTION CAUGHT BY WIDGETS LIBRARY โ•žโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
flutter: The following assertion was thrown building BlocBuilder<AuthenticationBloc, dynamic>(state:
flutter: _BlocBuilderBaseState<AuthenticationBloc, dynamic>#5b9f4):
flutter:         BlocProvider.of() called with a context that does not contain a Bloc of type
flutter: AuthenticationBloc.
flutter:         No ancestor could be found starting from the context that was passed to
flutter: BlocProvider.of<AuthenticationBloc>().
flutter:
flutter:         This can happen if:
flutter:         1. The context you used comes from a widget above the BlocProvider.
flutter:         2. You used MultiBlocProvider and didn't explicity provide the BlocProvider types.
flutter:
flutter:         Good: BlocProvider<AuthenticationBloc>(builder: (context) => AuthenticationBloc())
flutter:         Bad: BlocProvider(builder: (context) => AuthenticationBloc()).
flutter:
flutter:         The context used was: LoginPage(dirty, state: _LoginPageState#2cea8(lifecycle state:
flutter: created))

Can someone tell me what I'm doing wrong?

Here is my Flutter doctor output:

Doctor summary (to see all details, run flutter doctor -v):
[โœ“] Flutter (Channel stable, v1.7.8+hotfix.3, on Mac OS X 10.14.6 18G95, locale
    en-PL)

[โœ“] Android toolchain - develop for Android devices (Android SDK version 29.0.0)
[โœ“] Xcode - develop for iOS and macOS (Xcode 10.3)
[โœ“] iOS tools - develop for iOS devices
[โœ“] Android Studio (version 3.4)
[โœ“] VS Code (version 1.37.1)
[โœ“] Connected device (1 available)

โ€ข No issues found!
question

Most helpful comment

Hello! Can you please explain what was that mistake? Or share code of this project. Project page is currently unavailable, but it interesting)

All 29 comments

Hi @mariaszek9003 ๐Ÿ‘‹
Thanks for opening an issue!

Can you please share the link to an example app which illustrates the issue you're having so I can run and debug it locally?

Also, you can eliminate a lot of boilerplate code by refactoring your StatefulWidgets into StatelessWidgets. This is because BlocProvider will automatically dispose the blocs for you and BlocBuilder will automatically do the bloc lookup for you.

I've put together a gist with an updated version of the code you've provided. Let me know if that helps and if you're still having trouble please provide a link to a sample app ๐Ÿ‘

Thanks!

Hi @felangel, thank you for response.

I checked your gist if changing StatefulWidgets to StatelessWidgets help with the problem but unfortunately it doesn't.

Here is the repo: https://github.com/mariaszek9003/WeatherApp

Hi @mariaszek9003 thanks for the link! I took a look and opened 2 pull requests.

Hope that helps and sorry for the delayed response! ๐Ÿ‘

Hi @felangel thank you for fixing the issue - that was stupid mistake. Also thank you for code improvement suggestions.

Hello! Can you please explain what was that mistake? Or share code of this project. Project page is currently unavailable, but it interesting)

@ViktorJasch Hi! Sorry for late response. The cause of the problem was double slash that I made in importing statement in LoginPage file:

import "../blocs//authenticationBloc.dart";

it should be:

import "../blocs/authenticationBloc.dart";

Ola tenho um problema, esta aparecendo essa mensagem quando vou prover uma estancia
BlocProvider.of() called with a context that does not contain a Bloc of type ProcessoBloc.

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:legale/blocs/processo/processo.dart';
import 'package:legale/core/config/style.dart';
import 'package:legale/core/models/processo-model.dart';

// void main() {
// runApp(new MaterialApp(
// home:
// new ProcessoCardsScreen(),
// ));
// }

class ProcessoCardsScreen extends StatefulWidget {
final Processo processo;

const ProcessoCardsScreen({Key key, this.processo}) : super(key: key);
@override
_ProcessoCardsScreen createState() => _ProcessoCardsScreen();

}

class _ProcessoCardsScreen extends State {
ProcessoBloc _processoBloc;

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

@override
Widget build(BuildContext context) {
BlocProvider.of(context); // linha do erro
return BlocBuilder(
bloc: _processoBloc,
condition: (previousState, state) {
return previousState is DetalhesProcessoCarregado ||
state is DetalhesProcessoCarregado;
},
builder: (context, state) {
DetalhesProcessoCarregado currentState =
(state as DetalhesProcessoCarregado);
return new Scaffold(
appBar: AppBar(
title: Text('Processo'),
backgroundColor: LegaleStyle.colorPrimary,
),
body: ListView(
children: [

@Rodrigossff91 you need to provide the ProcessoBloc using BlocProvider somewhere in the widget tree

void main() {
  runApp(
    BlocProvider<ProcessoBloc>(
      builder: (_) => ProcessoBloc(),
      child: MaterialApp(
        home: ProcessoCardsScreen(),
      ),
    ),
  );
}

Then when you use BlocProvider.of you need to provide the bloc type so instead of

_processoBloc = BlocProvider.of(context);

you should do

_processoBloc = BlocProvider.of<ProcessoBloc>(context);

Hope that helps ๐Ÿ‘

tnks

Hi, I have the same issue @felangel ,
here is my code :
`import 'dart:async';

import 'package:meta/meta.dart';
import 'package:bloc/bloc.dart';

import '../repositories/user_repository.dart';
import './authentication.dart';

class AuthenticationBloc
extends Bloc {
final UserRepository userRepository;

AuthenticationBloc({@required this.userRepository})
: assert(userRepository != null);

@override
AuthenticationState get initialState => AuthenticationUninitialized();

@override
Stream mapEventToState(
AuthenticationEvent event,
) async* {
if (event is AppStarted) {
final bool hasToken = await userRepository.hasToken();

  if (hasToken) {
    yield AuthenticationAuthenticated();
  } else {
    yield AuthenticationUnauthenticated();
  }
}

if (event is LoggedIn) {
  yield AuthenticationLoading();
  await userRepository.persistToken(event.token);
  yield AuthenticationAuthenticated();
}

if (event is LoggedOut) {
  yield AuthenticationLoading();
  await userRepository.logout();
  yield AuthenticationUnauthenticated();
}

}
}`

and i called it like this :
InkWell(child: Text('logout'),onTap: ()=> BlocProvider.of(context).mapEventToState(LoggedOut()))

@areejmayadeh you need to add an event to the bloc:

InkWell(child: Text('logout'),onTap: ()=> BlocProvider.of<AuthenticationBloc>(context).add(LoggedOut())

@RollyPeres
BlocProvider.of<AuthenticationBloc>(context).mapEventToState(LoggedOut())
I have tried above, mapEventToState function add event but nothing happens

@RollyPeres when try using add function it keeps tell me undefined

You should not be using mapEventToState but instead use the way I suggested above.
Also make sure you have the latest version of bloc and flutter_bloc which is 4.0.0

I used it same as example

On Mon, Jun 1, 2020 at 9:37 PM Rolly Peres notifications@github.com wrote:

You should not be using mapEventToState but instead use the way I
suggested above.
Also make sure you have the latest version of bloc and flutter_bloc which
is 4.0.0

โ€”
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/felangel/bloc/issues/497#issuecomment-637034405, or
unsubscribe
https://github.com/notifications/unsubscribe-auth/AHKSKTYDBV5VRRUAS6DBRQLRUPYQHANCNFSM4ISUELMQ
.

Can you share a full repo/gist with your code?

@RollyPeres
I was having an issue with provider package I upgraded and the problem of add resolved
but when I try to call _onLoginButtonPressed() { BlocProvider.of<AuthenticationBloc>(context).mapEventToState( LoginButtonPressed( username: _usernameController.text, password: _passwordController.text, ), ); }
gives error :

The argument type 'LoginButtonPressed' can't be assigned to the parameter type 'AuthenticationEvent'.

@felangel Could you please check my issue, i did it same way as you did in your example flutter_login

@areejmayadeh can you please share a link to the full repository rather than individual files?

@areejmayadeh

Please remove the red line ๐Ÿ‘Ž and replace it with green line ๐Ÿ‘

onPressed: () {
   BlocProvider.of<AuthenticationBloc>(context)
- .mapEventToState(LoggedOut());
+ .add(LoggedOut());
 },

@felangel I send it by email for you

i also have same issue

error is

The following assertion was thrown building BlocConsumer(dirty):
BlocProvider.of() called with a context that does not contain a Bloc of type BillingBloc.

    No ancestor could be found starting from the context that was passed to BlocProvider.of<BillingBloc>().

    This can happen if the context you used comes from a widget above the BlocProvider.

    The context used was: BlocConsumer<BillingBloc, BillingState>(dirty)

The relevant error-causing widget was:
BlocConsumer file:///D:/flutter/za/lib/presentation/features/billing/billing_screen.dart:52:13
When the exception was thrown, this was the stack:

0 BlocProvider.of (package:flutter_bloc/src/bloc_provider.dart:106:7)

1 BlocConsumer.build (package:flutter_bloc/src/bloc_consumer.dart:102:44)

2 StatelessElement.build (package:flutter/src/widgets/framework.dart:4585:28)

3 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4511:15)

4 Element.rebuild (package:flutter/src/widgets/framework.dart:4227:5)

...
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

CODE

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:primedeal/config/routes.dart';
import 'package:primedeal/config/theme.dart';
import 'package:primedeal/domain/entities/validator.dart';
import 'package:primedeal/presentation/features/billing/billing.dart';
import 'package:primedeal/presentation/widgets/widgets.dart';
import 'package:primedeal/presentation/features/billing/billing_state.dart';

class BillingScreen extends StatefulWidget {
@override
State createState() {
return _BillingScreenState();
}
}

class _BillingScreenState extends State {
final TextEditingController stateController = TextEditingController();
final TextEditingController mobController = TextEditingController();
final TextEditingController cityController = TextEditingController();
final TextEditingController zipController = TextEditingController();
final TextEditingController nameController = TextEditingController();
final TextEditingController cnameController = TextEditingController();
final TextEditingController addController = TextEditingController();

final GlobalKey addKey = GlobalKey();
final GlobalKey stateKey = GlobalKey();
final GlobalKey nameKey = GlobalKey();
final GlobalKey cnameKey = GlobalKey();
final GlobalKey zipKey = GlobalKey();

final GlobalKey mobKey = GlobalKey();
final GlobalKey cityKey = GlobalKey();

double sizeBetween;

@override
Widget build(BuildContext context) {
var height = MediaQuery.of(context).size.height;
var width = MediaQuery.of(context).size.width;
sizeBetween = height / 20;
return Scaffold(
appBar: AppBar(
backgroundColor: AppColors.transparent,
brightness: Brightness.light,
elevation: 0,
iconTheme: IconThemeData(color: AppColors.black),
),
backgroundColor: AppColors.background,
body: BlocConsumer(
listener: (context, state) {
// on success delete navigator stack and push to home
if (state is BillingFinishedState) {
Scaffold.of(context).showSnackBar(

         SnackBar(
          content: Text(' ${state.message}'),
          backgroundColor: Colors.green, // TODO use app colors
          duration: Duration(seconds: 8),),

        );



      }
      // on failure show a snackbar
      if (state is BillingErrorState) {
        Scaffold.of(context).showSnackBar(
          SnackBar(
            content: Text('${state.error}'),
            backgroundColor: Colors.red,
            duration: Duration(seconds: 3),
          ),
        );
      }
    },
    builder: (context, state) {
      // show loading screen while processing
      if (state is BillingProcessingState) {
        return Center(
          child: CircularProgressIndicator(),
        );
      }
      return SingleChildScrollView(
        child: Container(
          height: height * 0.9,
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              OpenFlutterBlockHeader(title: 'Sign up', width: width),
              SizedBox(
                height: sizeBetween,
              ),
              OpenFlutterInputField(
                key: nameKey,
                controller: nameController,
                hint: 'Name',
                validator: Validator.valueExists,
              ),
              OpenFlutterInputField(
                key: cnameKey,
                controller: cnameController,
                hint: 'Company Name (optional)',
                validator: Validator.valueExists,
              ),

              OpenFlutterInputField(
                key: mobKey,
                controller: mobController,
                hint: 'Mobile number',
                keyboard:TextInputType.number ,
                validator: Validator.valueExists,
              ),
              OpenFlutterInputField(
                key: addKey,
                controller: addController,
                hint: 'Address',
                validator: Validator.valueExists,
              ),

              OpenFlutterInputField(
                key: cityKey,
                controller: cityController,
                hint: 'City',
                validator: Validator.valueExists,
              ),

              OpenFlutterInputField(
                key: stateKey,
                controller: stateController,
                hint: 'State',
                validator: Validator.validateEmail,
                keyboard: TextInputType.emailAddress,
              ),
              OpenFlutterInputField(
                key: zipKey,
                controller: zipController,
                hint: 'Password',
                validator: Validator.passwordCorrect,
                keyboard: TextInputType.visiblePassword,
                isPassword: true,
              ),
              OpenFlutterButton(
                  title: 'Update', onPressed: _validateAndSend),
              SizedBox(
                height: sizeBetween,
              ),
            ],
          ),
        ),
      );
    },
  ),
);

}

void _validateAndSend() {
BlocProvider.of(context).add(
BillingPressed(
name:nameController.text.toString(),
cname:cnameController.text.toString(),
state:stateController.text.toString(),
city:cityController.text.toString(),
add:addController.text.toString(),
phone:mobController.text.toString(),
zip:zipController.text.toString(),
),
);
}

}

@rnagar3434 you need to ensure you have provided a BillingBloc above your screen via

BlocProvider<BillingBloc>(create: (context) => BillingBloc())

Hi i have same error but i didnt find it
error is
BlocProvider.of() called with a context that does not contain a Cubit of type SearchBloc.

    No ancestor could be found starting from the context that was passed to BlocProvider.of<SearchBloc>().

    This can happen if the context you used comes from a widget above the BlocProvider.

    The context used was: Categories(dirty, state: _CategoriesState#d34a4(lifecycle state: created))

here is my code
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:wallpaper_app/data/models/photos_data.dart';
import 'package:wallpaper_app/presentation/blocs/search/search_bloc.dart';
import 'package:wallpaper_app/presentation/widgets/widgets.dart';

class Categories extends StatefulWidget {
final String name;

Categories(this.name);

@override
_CategoriesState createState() => _CategoriesState();
}

class _CategoriesState extends State {
PhotosData data = PhotosData();
TextEditingController controller = TextEditingController();
SearchBloc bloc;

@override
void initState() {
controller.text = widget.name;
bloc = BlocProvider.of(context)..add(SearchEvent(widget.name));
super.initState();
}

@override
void deactivate() {
super.deactivate();
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: brandName(),
elevation: 0.0,
),
body: SingleChildScrollView(
child: Container(
child: BlocBuilder(
cubit: bloc,
builder: (BuildContext context, state) {
if (state is LoadedSearchState)
return getCard(state.list ?? [], context);
else if (state is ErrorSearchState)
return Center(
child: Text("error"),
);
else
return CircularProgressIndicator();
},
),
),
),
);
}
}

Hi @umidshox99 ๐Ÿ‘‹

You need to actually provide your bloc above your Categories widget.

BlocProvider<SearchBloc>(create: (_) => SearchBloc(), child: ...);

@RollyPeres Hello thank u 4 r answer but I use MultiBlocProvider there is my code
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'WallpaperHub',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: Colors.white,
),
home: MultiBlocProvider(providers: [
BlocProvider(
create: (context) =>
SearchBloc(PhotosRepositoryImpl(APIProvider()))),
BlocProvider(
create: (context) =>
FetchTrendsBloc(PhotosRepositoryImpl(APIProvider()))),
], child: Home()),
);
}
}

You might be doing some navigation, so try and lift up your MultiBlocProvider above MaterialApp to make sure you have access to your bloc from any route.
Alternatively you could scope it to the needed screen.

@RollyPeres thank u bro it works erfectly

Was this page helpful?
0 / 5 - 0 ratings

Related issues

nosmirck picture nosmirck  ยท  30Comments

mikededo picture mikededo  ยท  28Comments

sawankumarbundelkhandi picture sawankumarbundelkhandi  ยท  108Comments

konstantin-doncov picture konstantin-doncov  ยท  30Comments

felangel picture felangel  ยท  27Comments