使用不包含类型Bloc的上下文调用Flutter BLoC BlocProvider.of

问题描述

类似于this thread,到目前为止,没有解决方案。

我收到以下错误

import Axios from 'axios';

export const LoginFn = (formData) => Axios.post("/auth/login",formData);

export const SignupFn = (formData) => Axios.post("/auth/signup",formData);

export const GetProfileFn = () => Axios.get("/auth/profile")

唯一的窗口小部件:

import React,{ useState } from 'react'
import { LoginFn } from '@Services/Auth'

export LoginPage = () => {
   const [isLoading,setIsLoading] = useState(false);

   const LoginHandler = (data) => {
     setIsLoading(true)
     LoginFn(data).then(({ data }) => {
       // do whatever you need
       setIsLoading(false)
    })
  }

  return (
    <form onSubmit={LoginHandler}>
     .......
  )
}

通过GetIt进行依赖注入

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

为完整起见,我将提供所有bloc文件

CategoryBloc

class _TestWidgetState extends State<TestWidget> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Test')),body: BlocProvider(
        builder: (context) => sl<CategoryBloc>(),// dependency injection via GetIt
        child: Column(
          children: [
            BlocBuilder<CategoryBloc,CategoryState>(builder: (context,state) {
              if (state is Empty) {
                return Text('Empty');
              }
              if (state is Loading) {
                return Text('Loading');
              }
              if (state is Loaded) {
                return Text('Loaded');
              }
            }),RaisedButton(
              child: Text('Press me'),onpressed: () {
                dispatchAction(context);
              },),],);
  }

  void dispatchAction(BuildContext context) {
    BlocProvider.of<CategoryBloc>(context).dispatch(GetAllCategories());
  }
}

CategoryEvent

 sl.registerFactory(() => CategoryBloc(getAllCategories: sl()));
...

类别状态

class CategoryBloc extends Bloc<CategoryEvent,CategoryState> {
  final GetAllCategoriesUsecase getAllCategories;

  CategoryBloc({@required this.getAllCategories})
      : assert(getAllCategories != null);

  @override
  CategoryState get initialState => Empty();

  @override
  Stream<CategoryState> mapEventToState(CategoryEvent event) async* {
    if (event is GetAllCategories) {
      yield Loading();
      final failureOrCategories =
          await getAllCategories(Params(limit: 10,skip: 0));
      yield failureOrCategories.fold(
          (failure) => Error(error: _mapFailuretoMessage(failure)),(categories) => Loaded(list: categories));
    }
  }

  String _mapFailuretoMessage(Failure failure) {
    ...
  }
}

pubspec.yaml

@immutable
abstract class CategoryEvent extends Equatable {
  CategoryEvent([List props = const <dynamic>[]]) : super();
}

class GetAllCategories extends CategoryEvent {
  @override
  List<Object> get props => [];
}

到目前为止,我已经尝试过:

  • 指定类型@immutable abstract class CategoryState extends Equatable { CategoryState([List props = const <dynamic>[]]) : super(); @override List<Object> get props => []; } class Empty extends CategoryState {} class Loading extends CategoryState {} class Loaded extends CategoryState { final List<Category> list; Loaded({@required this.list}); @override List<Object> get props => [list]; } class Error extends CategoryState { final String error; Error({@required this.error}); @override List<Object> get props => [error]; } -相同的错误

非常感谢任何帮助。

解决方法

经过数小时的Google搜索,找到了答案。

Flutter_bloc要求 BlocProvider BlocBuilder 必须位于单独的小部件中,以便Bloc Builder的上下文在该对象的上下文中层次化生成器。

class _TestWidgetState extends State<TestWidget> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Test')),body: BlocProvider<CategoryBloc>(
        builder: (context) => sl<CategoryBloc>(),//
        child: TestWidget2(),),);
  }
}

class TestWidget2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        BlocBuilder<CategoryBloc,CategoryState>(builder: (context,state) {
          if (state is Empty) {
            return Text('Empty');
          }
          if (state is Loading) {
            return Text('Loading');
          }
          if (state is Loaded) {
            return Text('Loaded');
          }
        }),RaisedButton(
          child: Text('Press me'),onPressed: () {
            dispatchAction(context);
          },],);
  }