So I heard a teacher saying he uses setState
when the code is simple enough, which I thought was bad, because then why should I use any state management library? Is it just to split code?
I also though setState
re-builds the whole screen in all instances but I discovered that this is not particularly correct? I thought I got the whole idea but I am a bit confused now..
My question here is when am I allowed to use setState
if I'm using bloc, riverpod, or anything? Like, what are my limits?
Should I use setState
with something like a navbar ? because NavBars rebuilds the whole screen in all cases and It's a lot easier and more readable if I just used setState
with it
First, you need to understand what kinds of state exist, and why state management libraries emerged. Flutter official docs and YouTube videos provide plenty of high-quality information on those topics. For instance, start with this introductory video.
In almost any application, there are two major types of state: app state (aka "global" or "app-wide" state) and ephemeral state (aka "local state"). The key difference between them is that the app state should be readily available for using (consuming) on any screen and in virtually any part of the application (eg. the app settings). In contrast, the ephemeral state usually only makes sense within a particular part of the app (eg. a boolean state of an expandable content block – collapsed or expanded). But in the end, this is your job, as a developer, to decide what in your app belongs to the app state vs ephemeral state. For instance, your app might need to know (on any screen and at any given moment) if the expandable block on the main screen is currently expanded or collapsed, because this knowledge somehow serves the app's business logic. In this case, the block's state would be a part of the app state.
So the Flutter's simplest state management mechanism StatefulWidget
+ setState
is more suitable for the ephemeral state because it doesn't allow for easy sharing of the state between screens and other widgets (and while it's possible to pass the state as widgets' arguments deep down the tree, this approach is obviously cumbersome and error-prone). Usually, setState
is more than enough to handle an ephemeral state.
As to the app state management, Flutter also provides a built-in mechanism for it called InheritedWidget but it's pretty limited and not well-suited for a whole range of use cases. That's why app state management libraries (such as Provider, Riverpod or Bloc) emerged – they are more geared towards the app's global state management. Competing with each other and offering different approaches, they try to make the app's global state management as simple and convenient as possible for developers.
Answering you main question – in general, it's perfectly fine to use the Flutter's built-in StatefulWidget
's setState
method alongside any app state management library (with rare exceptions probably), simply because these mechanisms have pretty different purposes and do not naturally conflict with each other. Moreover, most of the time you'll find yourself using a state management library alongside the InheritedWidget
because many things in Flutter depend on it behind the scene (eg. Theme.of(context)
), and this will not do any harm.
There is also an excellent thesis by Dmitrii Slepnev that compares the most popular State Management mechanisms and libraries for Flutter.