Flutter
setState pitfalls
Learn async setState and the mounted check.
The async setState trap
If you call setState after awaiting a Future, the widget may no longer be on screen; the user may have navigated away. In that case setState throws an error.
Future.delayed(Duration(seconds: 2), () {
setState(() { _data = 'ready'; });
});
To prevent this, you check mounted first.
mounted check
mounted tells whether the State object is currently in the widget tree. While it is true, setState is safe.
if (mounted) {
setState(() { _data = result; });
}
After dispose is called, mounted becomes false.
Exercise Load data async and call setState with mounted check
The veriCek method should wait 100 ms. Then check if (mounted) and use setState to set _veri to 'hazır', then call print(_veri).
Show example solution
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(home: VeriEkrani());
}
}
class VeriEkrani extends StatefulWidget {
@override
_VeriEkraniState createState() => _VeriEkraniState();
}
class _VeriEkraniState extends State<VeriEkrani> {
String _veri = 'yükleniyor';
@override
void initState() {
super.initState();
veriCek();
}
Future<void> veriCek() async {
await Future.delayed(Duration(milliseconds: 100));
if (mounted) {
setState(() {
_veri = 'hazır';
});
print(_veri);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(child: Text(_veri)),
);
}
}
Test yourself
-
What should be done before setState after an async operation?
- After an async operation, mounted is checked before setState
- mounted is only used inside initState
- mounted becomes true after State is disposed
- mounted is always true
Show answer
After an async operation, mounted is checked before setState — After async the widget may have left the tree; before setState, if (mounted) checks that the State is still in the tree.
-
Add the mounted check
Future<void> veriCek() async {
await Future.delayed(Duration(seconds: 1));
if (____) {
setState(() { _veri = 'hazır'; });
print(_veri);
}
}
Show answer
Future<void> veriCek() async {
await Future.delayed(Duration(seconds: 1));
if (mounted) {
setState(() { _veri = 'hazır'; });
print(_veri);
}
}
-
Async and mounted parts
- mounted
- Whether State is in the widget tree
- async
- Keyword marking functions that can await
- Future.delayed
- Runs a callback after a delay
- if (mounted)
- Safe setState call after async
Next lesson: State and performance