flutterblocflutter-blocfreezedflutter-freezed

BLoC builder doesn't rerender UI


I would like to get todos from API, set them to state and show them on screen. On initState method I am starting request. After recieving it in my BLoC, I set it in state. But todos don't visible on my screen and state is emty array.

My request from screen:

@override
  void initState() {
    todosBloc.add(TodosInitialFetchEvent());
    super.initState();
  }

Here is my BLoC file with state:

@freezed
abstract class TodosState with _$TodosState {
  const factory TodosState({
    required List<Todo> todos,
    @Default(false) bool loading,
  }) = _TodosState;
}

class TodosBloc extends Bloc<TodosEvent, TodosState> {
  TodosBloc() : super(const TodosState(todos: [])) {
    on<TodosInitialFetchEvent>(todosInitialFetchEvent);
  }

  FutureOr<void> todosInitialFetchEvent(event, Emitter<dynamic> emit) async {
    emit(state.copyWith(loading: true)); // try to set loading as true
    List<Todo> todos = await TodosRepo
        .getAllTodos(); // async operation to JSON placeholder API (works)
    emit(state.copyWith(
        todos: todos, loading: false)); // finish loading, apply recieved todos
    print(state.todos); // shows todos which were recieved
  }
}

Part of UI screen where I should see todos, but no:

@override
  Widget build(BuildContext context) {
    return Scaffold(body: BlocBuilder<TodosBloc, TodosState>(
      builder: (context, state) {
        print(state.todos); // shows empty array
        if (state.loading) {
          return const Center(
            child: CircularProgressIndicator(),
          );
        }

Solution

  • The solution is that I shouldn't create another instanse of bloc to call an event

    Was:

    final TodosBloc todosBloc = TodosBloc();
    

    Should be in initState:

    context.read<TodosBloc>().add(event);