Irbisa · Cheatsheet
Basic State Management
setState, InheritedWidget, ValueNotifier
Why do you need a state-management approach at all when
setStateexists?Which state-management approaches do you know in Flutter, and how do you choose one for a project?
How does
setState()work, what happens when you call it, and why must you not call it insidebuild()?class Counter extends StatefulWidget { const Counter({super.key}); @override State<Counter> createState() => _CounterState();}…Tapping this button calls
setState, yet the counter always shows 0. Why, and what else makessetStateseem to do nothing?class _CounterState extends State<Counter> { @override Widget build(BuildContext context) { int count = 0; return TextButton( onPressed: () => setState(() => count++), child: Text('$count'), ); }}What does it mean to "lift state up" in Flutter, and when should you do it?
class FilterBar extends StatefulWidget { const FilterBar({super.key}); @override State<FilterBar> createState() => _FilterBarState();}…Why must the callback you pass to
setStatebe synchronous, and what happens if you make itasync?// wrong: debug throws "setState() callback argument returned a Future"void _loadWrong() { setState(() async { _user = await api.fetchUser(); // assigned after the rebuild already ran });}…What has to be released in a State's
dispose(), and what goes wrong when you forget?class _EditorState extends State<Editor> with SingleTickerProviderStateMixin { final _text = TextEditingController(); final _focus = FocusNode(); late final AnimationController _anim; StreamSubscription<Draft>? _sub; Timer? _autosave;…What does this code print when the button is tapped once (not counting the initial
build: 0), and how many times doesbuildrun?class _DemoState extends State<Demo> { int _count = 0; void _tap() { setState(() => _count++); setState(() => _count++); setState(() => _count++); print('after: $_count'); } @override Widget build(BuildContext context) { print('build: $_count'); return TextButton(onPressed: _tap, child: Text('$_count')); }}A user double-taps Save and two orders get created. How do you stop the second tap with local state?
class _SaveButtonState extends State<SaveButton> { bool _saving = false; Future<void> _save() async { if (_saving) return; // the second tap lands here setState(() => _saving = true); // same synchronous slice: no race…What happens if you call
setStateafterdispose(), and why do you checkmountedafter everyawait?class _ProfilePageState extends State<ProfilePage> { Profile? _profile; Future<void> _refresh() async { final messenger = ScaffoldMessenger.of(context); // capture before the gap try {…What is the difference between
initStateanddidChangeDependencies?class _PostFeedState extends State<PostFeed> { FeedRepository? _repo; StreamSubscription<List<Post>>? _sub; List<Post> _posts = const []; @override…Find the bug: the parent resets the cart line to 1, but this quantity stepper keeps showing the old number.
class _QuantityStepperState extends State<QuantityStepper> { late int _qty; @override void initState() { super.initState(); _qty = widget.quantity; } void _inc() { setState(() => _qty++); widget.onChanged(_qty); } @override Widget build(BuildContext context) => TextButton(onPressed: _inc, child: Text('$_qty'));}What causes the "setState() or markNeedsBuild() called during build" error, and how do you fix it?
// wrong: the parent's setState runs while the tree is being builtclass _ItemsPanelState extends State<ItemsPanel> { @override Widget build(BuildContext context) { if (widget.items.isEmpty) widget.onEmpty(); // parent callback calls its setState return ItemList(widget.items);…A checkbox inside a dialog never updates when you call
setState. Why, and what is the fix?final accepted = await showDialog<bool>( context: context, builder: (dialogContext) { var agreed = false; // lives as long as this builder's closure return StatefulBuilder( builder: (context, setLocalState) => AlertDialog(…What is
ValueNotifier, how does it differ fromChangeNotifier, and when do you prefer it oversetState?class _FavoriteButtonState extends State<FavoriteButton> { final _liked = ValueNotifier<bool>(false); @override void dispose() { _liked.dispose();…An expensive chart inside a
ValueListenableBuilderrebuilds on every tick. What is the builder'schildparameter for?// wrong: a fresh ExpensiveChart instance on every tick, so it rebuildsValueListenableBuilder<int>( valueListenable: _ticks, builder: (context, ticks, _) => Column(children: [ Text('$ticks'), ExpensiveChart(series: widget.series),…A form rebuilds the whole page on every keystroke because
onChangedcallssetState. Where should that text actually live?// wrong: every keystroke rebuilds the page, and _text duplicates the truthTextField(onChanged: (v) => setState(() => _text = v)); // right: the controller is the source of truth; only the button listensclass _ComposerState extends State<Composer> { final _controller = TextEditingController();…What problem does
InheritedWidgetsolve, and how doesupdateShouldNotifywork?class AppColors extends InheritedWidget { const AppColors({super.key, required this.primary, required super.child}); final Color primary; static AppColors of(BuildContext context) {…How is
InheritedWidgetdifferent from Provider?What are the main criticisms of GetX, and why do many teams avoid it?
Find the bug in how this
CartBadgesubscribes to the cart, and fix it.class _CartBadgeState extends State<CartBadge> { @override void initState() { super.initState(); widget.cart.addListener(() => setState(() {})); } @override void dispose() { widget.cart.removeListener(() => setState(() {})); super.dispose(); } @override Widget build(BuildContext context) => Text('${widget.cart.count}');}What is the difference between
dependOnInheritedWidgetOfExactTypeandgetInheritedWidgetOfExactType, and why does a reader sometimes never rebuild?class CartScope extends InheritedWidget { const CartScope({super.key, required this.items, required super.child}); final List<Item> items; // registers this context as a dependent static CartScope of(BuildContext context) =>…Every widget that reads your
InheritedWidgetrebuilds when any single field changes. How do you make a reader depend on one field only?enum PrefAspect { currency, locale } class Prefs extends InheritedModel<PrefAspect> { const Prefs( {super.key, required this.currency, required this.locale, required super.child});…