avoid-unnecessary-setstate
preset: recommended
Warns when setState
is called inside initState
, didUpdateWidget
or build
methods and when it's called from a sync
method that is called inside those methods.
Calling setState in those cases will lead to an additional widget rerender which is bad for performance.
Consider changing state directly without calling setState
.
Additional resources:
Example
❌ Bad:
class MyWidget extends StatefulWidget {
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
String myString = '';
void initState() {
super.initState();
// LINT
setState(() {
myString = "Hello";
});
if (condition) {
// LINT
setState(() {
myString = "Hello";
});
}
myStateUpdateMethod(); // LINT
}
void didUpdateWidget(MyWidget oldWidget) {
// LINT
setState(() {
myString = "Hello";
});
}
void myStateUpdateMethod() {
setState(() {
myString = "Hello";
});
}
Widget build(BuildContext context) {
// LINT
setState(() {
myString = "Hello";
});
if (condition) {
// LINT
setState(() {
myString = "Hello";
});
}
myStateUpdateMethod(); // LINT
return ElevatedButton(
onPressed: () => myStateUpdateMethod(),
onLongPress: () {
setState(() {
myString = data;
});
},
child: Text('PRESS'),
);
}
}
✅ Good:
class MyWidget extends StatefulWidget {
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
String myString = '';
final classWithMethod = SomeClassWithMethod();
void initState() {
super.initState();
myString = "Hello";
classWithMethod.myMethod();
myAsyncMethod();
}
void didUpdateWidget(MyWidget oldWidget) {
myString = "Hello";
}
void myStateUpdateMethod() {
setState(() {
myString = "Hello";
});
}
Future<void> myAsyncMethod() async {
final data = await service.fetchData();
setState(() {
myString = data;
});
}
Widget build(BuildContext context) {
myAsyncMethod();
return ElevatedButton(
onPressed: () => myStateUpdateMethod(),
onLongPress: () {
setState(() {
myString = data;
});
},
child: Text('PRESS'),
);
}
}