6 easy tips when working with setState in a Flutter application

Flutter category image

The setState function is the most basic approach to managing your state in a Flutter app. Here are some best practices to keep your app maintainable.

The setState function of the StatefulWidget is a simple approach to managing the state within a Flutter app. But there are several pitfalls you need to avoid when you want your app to be working and performant. Here are some best practices you should stick to.

What is setState good for?

setState is the Flutter way to issue a rebuild of the current widget and its descendants. During a rebuild, the most recent variable values will be used to create the user interface. Let’s say, a user toggles a switch from on to off. The switch has a backing variable that stores that value, so after the change, it is set to false. The switch itself doesn’t reflect that change until it is rebuilt with its new backing field value.

▶ Change a value
▶ Call setState()
▶ User interface is updated

? Tip 1: Keep your widgets small!

setState triggers a rebuild of the widget that you are currently in. If your whole application contains only one widget, then this whole widget will be rebuilt which makes your app slow. See the following example:

Here we have 5 SwitchListTile widgets in a Column and they are all part of the same widget. If you switch any control, the entire screen gets rebuilt. ScaffoldAppBarColumn, … but it would be enough to just rebuild the widget that has changed. Let’s look at the next code example:

Here we wrapped the SwitchListTile in a single StatefulWidget. The pages look identical, but if you click on any switch in this example, only the clicked widget will rebuild. You won’t notice any performance enhancements for this small case but on a larger scale, it will make a difference.

? Tip 2: Don’t call setState in build methods

From the Flutter API documentation

This method can potentially be called in every frame and should not have any side effects beyond building a widget.

The build method is intended to build the widget tree, so we should keep it that way. Don’t do fancy stuff here, it will slow down your app. Calls to setState will probably trigger additional rebuilds and in the worst case, you might end up having an exception telling you that there is currently a rebuild in progress.

? Tip 3: Don’t call setState in initState methods

initState will trigger a rebuild after completion so it’s not necessary to call setState inside this method. This method is intended to initialize state-relevant properties like setting default values or subscribing to streams. Don’t do anything else here!

? Tip 4: setState() and setState(…) are equal

It doesn’t matter if you use setState like this

_text = “Hello”;

or like this

_text = “Hello”;

The outcome is the same.

? Tip 5: setState(…) code must be small

Don’t do any big computations within setState because it will block your app from rebuilding the screen. Look at the following sample code:

setState(() {
for (var i = 0; i < 10000; i++) print(i);
_value = true;

Only after the print statements, the widget will rebuild. During that time your app doesn’t respond to user actions and it will perform them afterward. So if a user clicks on a control multiple times because there is no visual feedback, multiple rebuilds are stacked up and will slow down the app even more.

A better approach is to show a progress indicator while performing a long-running operation so that the user knows that something is happening and he needs to wait for the completion.

? Tip 6: setState(…) code must not be async

When running the code

setState(() async {
  await Future.delayed(const Duration(seconds: 5));

you will end up with an exception message like this:

Exception when using async code in setState
Exception when using async code in setState

Perform your async operations outside of the method and call it afterward.


I hope these insights help you better understand the mechanics of setState in Flutter. Stick to these tips and you’ll have fewer problems and faster apps. Source code examples can be found on GitHub.

Related articles