Line data Source code
1 : import 'package:flutter/widgets.dart'; 2 : import 'package:flutter_hooks_bloc/src/bloc_hook.dart'; 3 : import 'package:flutter_hooks_bloc/src/flutter_bloc.dart' hide BlocProvider; 4 : 5 : /// Signature for the `builder` function which takes the `BuildContext` and 6 : /// [state] and is responsible for returning a widget which is to be rendered. 7 : /// This is analogous to the `builder` function in [StreamBuilder]. 8 : typedef BlocWidgetBuilder<S> = Widget Function(BuildContext context, S state); 9 : 10 : /// Signature for the `buildWhen` function which takes the previous `state` and 11 : /// the current `state` and is responsible for returning a [bool] which 12 : /// determines whether to rebuild [BlocBuilder] with the current `state`. 13 : typedef BlocBuilderCondition<S> = bool Function(S previous, S current); 14 : 15 : /// {@template bloc_builder} 16 : /// Please refer to `BlocListener` if you want to "do" anything in response to 17 : /// `state` changes such as navigation, showing a dialog, etc... 18 : /// 19 : /// 20 : /// ```dart 21 : /// BlocBuilder<BlocA, BlocAState>( 22 : /// builder: (context, state) { 23 : /// // return widget here based on BlocA's state 24 : /// } 25 : /// ) 26 : /// ``` 27 : /// 28 : /// Only specify the [bloc] if you wish to provide a [bloc] that is otherwise 29 : /// not accessible via the current `BuildContext`. 30 : /// 31 : /// ```dart 32 : /// BlocBuilder<BlocA, BlocAState>( 33 : /// cubit: blocA, 34 : /// builder: (context, state) { 35 : /// // return widget here based on BlocA's state 36 : /// } 37 : /// ) 38 : /// ``` 39 : /// {@endtemplate} 40 : /// {@template bloc_builder_build_when} 41 : /// An optional [buildWhen] can be implemented for more granular control over 42 : /// how often [BlocBuilder] rebuilds. 43 : /// [buildWhen] will be invoked on each [bloc] `state` change. 44 : /// [buildWhen] takes the previous `state` and current `state` and must 45 : /// return a [bool] which determines whether or not the [builder] function will 46 : /// be invoked. 47 : /// The previous `state` will be initialized to the `state` of the [bloc] when 48 : /// the [BlocBuilder] is initialized. 49 : /// [buildWhen] is optional and if omitted, it will default to `true`. 50 : /// 51 : /// ```dart 52 : /// BlocBuilder<BlocA, BlocAState>( 53 : /// buildWhen: (previous, current) { 54 : /// // return true/false to determine whether or not 55 : /// // to rebuild the widget with state 56 : /// }, 57 : /// builder: (context, state) { 58 : /// // return widget here based on BlocA's state 59 : /// } 60 : ///) 61 : /// ``` 62 : /// {@endtemplate} 63 : class BlocBuilder<B extends BlocBase<S>, S extends Object> 64 : extends BlocWidget<B, S> { 65 : ///The [BlocBuilder] constuctor builds a widget when a `bloc` state change. 66 3 : const BlocBuilder({ 67 : Key? key, 68 : 69 : /// The [bloc] that the [BlocBuilder] will interact with. 70 : /// If omitted, [BlocBuilder] will automatically perform a lookup using 71 : /// the current `BuildContext`. 72 : B? bloc, 73 : required this.builder, 74 : this.buildWhen, 75 3 : }) : super(key: key, bloc: bloc); 76 : 77 : /// The [builder] function which will be invoked on each widget build. 78 : /// The [builder] takes the `BuildContext` and current `state` and 79 : /// must return a widget. 80 : /// This is analogous to the [builder] function in [StreamBuilder]. 81 : final BlocWidgetBuilder<S> builder; 82 : 83 : ///{@macro bloc_builder_build_when} 84 : final BlocBuilderCondition<S>? buildWhen; 85 : 86 3 : @override 87 : Widget build(BuildContext context) { 88 3 : final state = $use(); 89 3 : return builder(context, state); 90 : } 91 : 92 2 : @override 93 : bool onStateEmitted(BuildContext context, S previous, S state) { 94 2 : return buildWhen?.call(previous, state) ?? true; 95 : } 96 : }