Error BlocProvider.of() called with a context That doesn't contain A bloc of type UserBloc

Viewed 1817

image

Anyone know what should I do with this? I making a user's listview, it should show appbar, tabbar userlist, user group, and the list of all users.

When I'm not using model and repository and just put the data manually on the users_page.dart, everything was fine, the layout showing. But it's happen idk what to do.

4 Answers

If you want to get the BLoC from a BlocProvider.of(context) you need to provide that BLoC somewhere on top of your current context. You need something like this:

BlocProvider(
  create: (BuildContext context) => UsersBloc(),
  child: child(),
);

In one of the ancestors of your UsersPage. Basically you need to tell from where to get an instance of your BLoC in that widget tree. Normally i write those BlocProviders in the MaterialApp, ensuring that every page will have those blocs in theirs context.

Error Picture

this is my UsersBloc:

import 'package:bloc/bloc.dart';
import 'package:merchant/feature/bloc/users/users_event.dart';
import 'package:merchant/feature/bloc/users/users_state.dart';

class UsersBloc
extends Bloc < UsersEvent, UsersState > {
  int currentIndex = 0;

  @override
  UsersState get initialState => UsersLoading();

  @override
  Stream < UsersState > mapEventToState(UsersEvent event) async * {
    if (event is UsersStarted) {
      this.add(UsersTapped(index: this.currentIndex));
    }

    if (event is UsersTapped) {
      this.currentIndex = event.index;
      yield CurrentIndexChanged(currentIndex: this.currentIndex);
      yield UsersLoading();

      if (this.currentIndex == 0) {
        //        String data = await UsersRepository();
        yield UsersListLoaded(text: "UsersList");
      }

      if (this.currentIndex == 1) {
        //        String data = await UsersRepository();
        yield UsersGroupLoaded(text: "UsersGroup");
      }

      if (event is UsersDetailTapped) {
        yield UsersDetailLoaded(text: "UserDetail");
      }
    }
  }
}

this is my UsersPage :

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:merchant/component/widget/loading_widget.dart';
import 'package:merchant/feature/bloc/users/users_bloc.dart';
import 'package:merchant/feature/bloc/users/users_event.dart';
import 'package:merchant/feature/bloc/users/users_state.dart';
import 'package:merchant/feature/splash_page.dart';
import 'package:merchant/feature/ui/users/users_list_tab.dart';
import 'package:merchant/feature/ui/users/users_group_tab.dart';

class UsersPage extends StatelessWidget {
  final String text;

  const UsersPage(this.text): super();
  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 2,
      child: Scaffold(
        appBar: AppBar(
          title: Text(
            "Users (UKSW)",
            style: TextStyle(color: Colors.white),
          ),
          bottom: TabBar(
            onTap: (index) => BlocProvider.of < UsersBloc > (context).add(UsersTapped(index: index)),
            isScrollable: true,
            labelColor: Colors.white,
            unselectedLabelColor: Colors.black54,
            tabs: [
              Tab(text: "User List"),
              Tab(text: "User Group"),
            ],
          ),
          actions: [
            IconButton(icon: Icon(Icons.search),
              onPressed: () {}
            )
          ]
        ),
        body: BlocBuilder < UsersBloc, UsersState >

        ( //bloc: BlocProvider.of<UsersBloc>(context),
          builder: (context, state) {
            if (state is UsersLoading) {
              return LoadingWidget(visible: true);
            }
            if (state is UsersListLoaded) {
              return UsersList();
            } else if (state is UsersGroupLoaded) {
              return UsersGroup();
            }
            return SplashPage();
          }
        )
      ));
  }
}

this is my users_model.dart :

import 'dart:convert';

class UsersModel {
  String name, username;

  UsersModel({
    this.name,
    this.username
  });

  factory UsersModel.fromJson(Map<String, dynamic> json) => UsersModel(
    name: json['name'],
    username: json['username']
  );
}

can you try initialising your bloc at the root of your app something like this

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: BlocProvider< UsersBloc >(
        create: (context) => UsersBloc(),
        child: UsersPage(),
      ),
    );
  }
}

then in your UsersPage file initialise bloc and assign it to variable and use it across.

Widget build(BuildContext context) {
 final UsersBloc usersBloc = BlocProvider.of<UsersBloc>(context);
 return DefaultTabController(
 length: 2,
 ... 
 bottom: TabBar(
   onTap: (index) => usersBloc.add(UsersTapped(index: index),
    ...)
 }

I have the same problem if you are calling from a non-bloc (Normal class) to a new bloc class without any bloc changes to the main class (Multi-bloc provider to runApp). Then add

Navigator.push(
  context,
  MaterialPageRoute(
    builder: (context) => 
     BlocProvider<UsersBloc>(
     create: (context) => UsersBloc(), 
     child: UsersBlocPage(),
    ),
  ));

This to your calling sequence. It works for me

Related