![]() |
VOOZH | about |
The Replay is a weekly newsletter for dev and engineering leaders.
Delivered once a week, it's your curated guide to the most important conversations around frontend dev, emerging AI tools, and the state of modern software.
To build any application in Flutter, we must create a widget class, which is the building block of a Flutter application. Flutter uses widgets to create modern mobile apps.
π The Difference Between Stateless and Stateful Widgets in FlutterWidgets in Flutter are classified into two types: stateless widgets and stateful widgets. Having that in mind, we will be looking at what stateless and stateful widgets are in Flutter and explaining their differences.
Letβs start with this question: What is the state of a widget in Flutter?
A state is when the information of a widget class is read synchronously during build time β that is, when the widget is displayed on the screen and might change if the information is altered during its lifetime.
Flutter has several built-in widgets, and all of them are classified into stateful and stateless widgets.
A stateless widget cannot change its state during the runtime of a Flutter application. That means a stateless widget cannot be redrawn while the app is in action. For that reason, the appearance and properties remain unchanged throughout the lifetime of the widget.
Stateless widgets can be useful when the part of the UI we are describing does not depend on any other widget. Examples of stateless widgets are text, icons, icon buttons, and raised buttons.
This is an example of a stateless widget:
class StatelessScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('LogRockets'),
backgroundColor: Colors.blueGrey[600],
),
backgroundColor: Colors.white,
body: Container(),
),
);
}
}
We can see that in the code, the name of the stateless widget is StatelessScreen and it is overriding the build method. The build method takes the BuildContext as a parameter and returns a widget.
We use a stateless widget when we create an application that isnβt required to redraw a widget again and again. For example, when we are creating an AppBar, a stateless widget can be scaffolding or icons that do not need to be changed.
A stateless widget class is called once, only when it is initialized. Even if an external force acts on it, it wonβt be updated.
Whenever the StatelessScreen widget is initialized, the build method is called. After that, the widget will be printed on the screen.
But if we want it to be updated once there is an action, we have to make a stateful widget.
A stateful widget is used when some part of the UI must change dynamically during runtime. Stateful widgets can redraw themselves multiple times while the app is running.
Stateful widgets are useful when the part of the UI we are describing changes dynamically. If we create a button widget that updates itself each time a user clicks that button, that is a stateful widget.
This is how you could use a stateful widget:
class StatefulScreen extends StatefulWidget {
@override
_StatefulScreenState createState() => _StatefulScreenState();
}
class _StatefulScreenState extends State<StatefulScreen> {
String title = 'Original title';
@override
Widget build(BuildContext context) {
return Column(children: [
Text(title),
RaisedButton(
child: Text('Click'),
onPressed: () {
setState(() {
title = 'Changed title';
});
})
]);
}
}
We created a text field and a button widget.
Once we call this widget and press the button, we let the value of the text field change automatically.
In this type of application, we can do that by the implementation of setState(). setState() is a method that is called within stateful widget classes. This method changes the value of a stateful widget each time it is called.
To recap what weβve illustrated in the examples above, this table describes the differences between a stateless and stateful widget:
| Stateless widget | Stateful widget |
|---|---|
| Only updates when it is initialized | Changes dynamically |
Text, icons, and RaisedButtons |
Checkboxes, radio buttons, and sliders |
Does not have a setState(). It will be rendered once and will not update itself |
Has an internal setState() and can re-render if the input data changes |
| Static widget | Dynamic widget |
| Canβt update during runtime unless an external event occurs | Can update during runtime based on user action or data changes |
Note that for both widgets to be created, they need BuildContext as a parameter that returns the widget.
Weβve covered the differences between stateful and stateless widgets to help you build better Flutter applications. From the examples, we learned what stateless and stateful widgets do and how to know which class is needed for your use case.
Now, you can create a better UI with widgets for different use cases.
Install LogRocket via npm or script tag. LogRocket.init() must be called client-side, not
server-side
$ npm i --save logrocket
// Code:
import LogRocket from 'logrocket';
LogRocket.init('app/id');
// Add to your HTML:
<script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script>
<script>window.LogRocket && window.LogRocket.init('app/id');</script>
TSRX adds first-class control flow, conditional hooks, and scoped styles to React via a TypeScript compiler extension β no new framework required.
Learn how to build a full React Native auth system using Better Auth and Expo β with email/password login, Google OAuth, session persistence, and protected routes.
Compare the top AI development tools and models of June 2026. View updated rankings, feature breakdowns, and find the best fit for you.
Learn how Bloom filters reduce database lookups for username availability checks while preserving correctness at scale.
Hey there, want to help make our blog better?
Join LogRocketβs Content Advisory Board. Youβll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up now