Managing state in Flutter? Oh boy, that was a rollercoaster ride for me! 🎢 When I first got into Flutter, handling state was one of the trickiest parts. I tried different approaches, hit roadblocks (a lot of them), and had my fair share of "Why is this not working?!" moments. So, here’s my experience—what worked, what didn’t, and how you can avoid some of the pain I went through. Let’s dive in!
What is State in Flutter? 🤔
Alright, let’s keep it simple. State is just the data that your UI depends on. If the state changes, your UI updates—like magic! 🎩✨
Flutter splits state into two types:
Ephemeral State
– Short-lived and local to a widget (e.g., TextEditingController, animations).App State
– Global state that multiple widgets need access to (e.g., authentication, themes, user settings).
Different Ways to Manage State 🚀
Flutter gives us multiple ways to handle state, each with its own pros and cons. Let’s break them down!
1. setState
– The Quick & Dirty Way
If your state is local to a single widget, setState
is your best friend.
class CounterScreen extends StatefulWidget {
@override
_CounterScreenState createState() => _CounterScreenState();
}
class _CounterScreenState extends State<CounterScreen> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(child: Text('Counter: $_counter')),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
child: Icon(Icons.add),
),
);
}
}
Pros:
✅ Super simple
✅ No extra dependencies
Cons:
❌ Can get messy in larger apps
❌ Not great for shared state
2. InheritedWidget – The Hidden Gem
This is Flutter’s built-in way to pass state down the widget tree. It’s powerful but... kinda verbose.
Pros:
✅ No external dependencies
✅ Efficient state propagation
Cons:
❌ A bit too much boilerplate for my taste
❌ Can be tricky to use correctly
3. Provider – The Community Favorite
I love Provider
! It’s simple, scalable, and widely used in Flutter apps.
class Counter with ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners();
}
}
Then wrap your app with ChangeNotifierProvider
and boom! Your state is now easily accessible.
Pros:
✅ Easy to use
✅ Scales well
Cons:
❌ Slight learning curve
4. Riverpod – Provider, But Cooler?
If Provider
is good, Riverpod
is like its smarter cousin. It removes some of the annoyances of Provider.
Pros:
✅ No BuildContext issues
✅ Cleaner API
Cons:
❌ Takes some getting used to
5. Bloc/Cubit – The Big Boss
If your app has complex state logic, Bloc
is a lifesaver. It’s structured, predictable, and makes debugging easier.
Pros:
✅ Super organized
✅ Great for large apps
Cons:
❌ Lots of boilerplate
❌ Feels overkill for small projects
The Problems I Faced & How I Solved Them 🛠️
1. Unnecessary Widget Rebuilds – My app got laggy because of too many rebuilds! Using Selector in Provider or Bloc’s Equatable fixed this.
2. State Persistence – Lost data when navigating between screens? Either keep state globally (Provider) or save it locally with Hive.
3. Which One to Choose? – I wasted weeks switching between Provider, Riverpod, and Bloc. My advice? Start simple (setState), then scale up when needed.
My Takeaways 🎯
If you’re new, start with
setState
. Just get comfortable with state changes.For medium-sized apps,
Provider
is your best bet.If your app is getting complex, go for
Riverpod
orBloc
.
At the end of the day, there’s no perfect state management solution—it all depends on your app’s needs. My journey has been full of trial and error, but figuring out the right approach has made me a better Flutter developer.
What’s your favorite way to handle state in Flutter? Let’s chat in the comments! 🚀
Let's Connect! 🎉
If you found this helpful and want to stay updated with more Flutter tips, feel free to follow me:
Dev.to: https://dev.to/thinnakrit
LinkedIn: https://www.linkedin.com/in/thinnakrit
GitHub: https://github.com/thinnakrit
Happy coding! 😊
Top comments (0)