skip to Main Content

according to the flutter_bloc documentation it is sufficient to wrap a widget with Bloc Provider in order to use the Bloc instance from the widget. However, I am getting this error:

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

My code is very simple, structured in the following way:

login_screen.dart

class LoginPage extends StatefulWidget {
  const LoginPage({super.key, required this.title});

  final String title;

  @override
  State<LoginPage> createState() => _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {
  
  final TextEditingController _usernameController = TextEditingController();
  final TextEditingController _passwortController = TextEditingController();

  @override
  Widget build(BuildContext context) {

    return BlocProvider(
      create: (context) => AuthenticationBloc(),
      child: Scaffold(
          appBar: AppBar(
            backgroundColor: Theme.of(context).colorScheme.inversePrimary,
            title: Text(widget.title),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [

                //Username
                Padding(
                  padding: const EdgeInsets.all(16.0),
                  child: TextField(
                    controller: _usernameController,
                    decoration: const InputDecoration(
                      labelText: "Email",
                      border: OutlineInputBorder()
                    ),
                  ),
                ),
    
                //Passwort:
                Padding(
                  padding: const EdgeInsets.all(16.0),
                  child: TextField(
                    controller: _passwortController,
                    obscureText: true,
                    decoration: const InputDecoration(
                      labelText: "Password",
                      border: OutlineInputBorder()
                    ),
                  ),
                ),
    
                //Login button
                ElevatedButton(
                  style: ElevatedButton.styleFrom(
                    minimumSize: const Size(200, 50)
                  ),
                  onPressed: () {

                    BlocProvider.of<AuthenticationBloc>(context).add(
                      LoginEvent(_usernameController.text, _passwortController.text)
                    );
    
                  }, 
                  child: const Text('Log in')
                ),
                const SizedBox(height: 20,),
                //Register button
                ElevatedButton(
                  style: ElevatedButton.styleFrom(
                    minimumSize: const Size(200, 50)
                  ),
                  onPressed: () async {
    
                  },
                  child: const Text('Register')
                ),
              ],
            ),)
        ),
    );
  }
}

main.dart

void main() async {

  WidgetsFlutterBinding.ensureInitialized();

  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );

  await service_registration.init();

  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const LoginPage(title: 'Flutter Demo Home Page'),
    );
  }
}

Any idea why this is happening?

2

Answers


  1. Have you tried to rename "context" in create parameter to something else?

    from:

    create: (context) => AuthenticationBloc()
    

    to

    create: (context2) => AuthenticationBloc()
    

    Sometimes happens to get the wrong context and, obviously, there will be no Bloc there.

    But I highly recommend you to provide blocs right before MaterialApp, on MyApp class. Just like below:

      class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      @override
      Widget build(BuildContext context) {
        return MultiBlocProvider(
          providers: [
            BlocProvider(
              create: (context) => AuthenticationBloc(),
            ),
            BlocProvider(
              create: (context) => MySecondBloc(),
            ),
          ],
          child: MaterialApp(
            title: 'Flutter Demo',
            theme: ThemeData(
               colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
               useMaterial3: true,
            ),
          home: const LoginPage(title: 'Flutter Demo Home Page'),
          ),
        );
      }
    }
    

    By doing this, you can access your bloc anywhere your application. Just be aware to not fetch a big amount of data right on blocstart

    Login or Signup to reply.
  2. BlocProvider.of() Fails to Find Bloc

    You cannot access a bloc from the same context in which it was provided so you must ensure BlocProvider.of() is called within a child BuildContext.

    The problem is that BlocProvider.of() is using the context that was provided for BlocProvider.

     BlocProvider.of<AuthenticationBloc>(context).add(LoginEvent(_usernameController.text, _passwortController.text));
    

    There are many ways to solve this issue; you just need to ensure that blocProvider.of() uses the child BuildContext. For example, you can wrap your Scaffold with BlocBuilder(), BlocConsumer(), or Builder().

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search