build_when

The better way to use BlocBuilder - simplify your buildWhen logic with declarative filters.

codecov GitHub License

Usage

Basic Example

Instead of writing verbose buildWhen logic:

// ❌ Verbose BlocBuilder
BlocBuilder<UserBloc, UserState>(
  buildWhen: (previous, current) => previous.name != current.name,
  builder: (context, state) => Text('Name: ${state.name}'),
)

Use BuildWhen with a simple filter:

// ✅ Clean BuildWhen
BuildWhen<UserBloc, UserState>(
  filter: (state) => state.name,
  builder: (context, state) => Text('Name: ${state.name}'),
)

BuildWhen - Single Filter

Rebuilds only when the specified filter value changes:

BuildWhen<UserBloc, UserState>(
  filter: (state) => state.name,
  builder: (context, state) => Text('Name: ${state.name}'),
)

BuildWhenSome - Any Filter Changes

Rebuilds when any of the specified filters change:

BuildWhenSome<UserBloc, UserState>(
  filterSome: [
    (state) => state.name,
    (state) => state.age,
  ],
  builder: (context, state) => Text('Name: ${state.name}, Age: ${state.age}'),
)

BuildWhenAll - All Filters Change

Rebuilds only when all of the specified filters change:

BuildWhenAll<UserBloc, UserState>(
  filterAll: [
    (state) => state.name,
    (state) => state.age,
  ],
  builder: (context, state) => Text('Name: ${state.name}, Age: ${state.age}'),
)

Smart Comparisons

build_when automatically handles:

  • Primitives - Strings, numbers, booleans, etc.
  • Null values - Properly detects null-to-value and value-to-null changes
  • Collections - Uses Flutter's listEquals, mapEquals, and setEquals for deep comparison
// Works with collections too!
BuildWhen<UserBloc, UserState>(
  filter: (state) => state.items, // List<String>
  builder: (context, state) => Text('Items: ${state.items.length}'),
)

Complete Example

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

class UserState {
  final String name;
  final int age;

  UserState({required this.name, required this.age});

  UserState copyWith({String? name, int? age}) {
    return UserState(
      name: name ?? this.name,
      age: age ?? this.age,
    );
  }
}

class ExamplePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          // Rebuild only when name changes
          BuildWhen<UserBloc, UserState>(
            filter: (state) => state.name,
            builder: (context, state) => Text('Name: ${state.name}'),
          ),

          // Rebuild when name OR age changes
          BuildWhenSome<UserBloc, UserState>(
            filterSome: [
              (state) => state.name,
              (state) => state.age,
            ],
            builder: (context, state) => Text('Name: ${state.name}, Age: ${state.age}'),
          ),
        ],
      ),
    );
  }
}

License

MIT

Libraries

build_when
A Flutter package that simplifies BlocBuilder usage with declarative filters.