flutter_super_state is a new state management library for Flutter which:
- Is simple to use. Simply create modules
- Supports
async
actions easily - Can easily be integrated with Flutter
Today we will take a look at creating a simple application with a mock authentication and a counter.
Concepts
Super State has 2 main objects:
-
Store
: Which holds all of your modules -
StoreModule
: Which you can extend to implement modules
Let's take a look at a simple module:
import 'package:flutter_super_state/flutter_super_state.dart';
// Modules extend `StoreModule`
class CounterModule extends StoreModule {
// Read only property, to avoid accidentally setting `counter` without calling `setState`
int get counter => _counter;
var _counter = 0;
// This automatically registers your module to your store
CounterModule(Store store): super(store);
// Synchronous actions
void increment() {
setState(() {
_counter++;
});
}
void decrement() {
setState(() {
_counter--;
});
}
// Asynchronous action
Future<void> reset() async {
// Fake async delay
await Future.delayed(Duration(milliseconds: 10));
setState(() {
_counter = 0;
});
}
}
A store is easy to setup, here's an example:
import 'package:flutter_super_state/flutter_super_state.dart';
final store = Store();
// Register modules. Order does not matter. You should register all modules on initialization
CounterModule(store);
You can then call get modules from the store and call actions:
store.getModule<CounterModule>().increment();
await store.getModule<CounterModule>().reset();
For Flutter integration, the package provides for following widgets:
-
StoreProvider
: Provides the store to all children in sub-tree -
ModuleBuilder
: Access a module inside the Flutter widget tree (is updated when module callssetState
) -
StoreBuilder
: Access the store inside the Flutter widget tree (is updated when any module callssetState
)
Example
Let's start by creating a new project using flutter create super_state_example
and adding the package to pubspec.yaml
:
dependencies:
flutter_super_state: # Optionally put latest version from pub.dev
Next, let's clear your main.dart
, and place our CounterModule
from above inside lib/src/store/counter.dart
. Let's create our second module, AuthModule
(inside lib/src/store/auth.dart
):
import 'package:flutter_super_state/flutter_super_state.dart';
import 'package:state_test/src/store/counter.dart';
class AuthModule extends StoreModule {
int get isLoggedIn => isLoggedIn;
var _isLoggedIn = false;
AuthModule(Store store) : super(store);
Future<void> login() async {
// Do network request...
await Future.delayed(Duration(milliseconds: 100));
setState(() {
_isLoggedIn = true;
});
}
Future<void> logout() async {
// Do network request...
await Future.delayed(Duration(milliseconds: 100));
setState(() {
_isLoggedIn = true;
});
// Call action in other module
await store.getModule<CounterModule>().reset();
}
}
We should have our modules complete! Next, let's setup 2 screens (LoginScreen
and CounterScreen
):
class LoginScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Login"),
),
body: Center(
// Login button
child: ModuleBuilder<AuthModule>(
builder: (context, authModule) {
return RaisedButton(
child: Text("Login"),
onPressed: () async {
// Call action
await authModule.login();
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => CounterScreen()),
);
},
);
},
),
),
);
}
}
class CounterScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Counter"),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
// Our counter module
ModuleBuilder<CounterModule>(
builder: (context, counterModule) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
child: Text("Increment"),
onPressed: () => counterModule.increment(),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Text(counterModule.counter.toString()),
),
RaisedButton(
child: Text("Decrement"),
onPressed: () => counterModule.decrement(),
),
],
);
},
),
// Logout button
ModuleBuilder<AuthModule>(
builder: (context, authModule) {
return RaisedButton(
child: Text("Logout"),
onPressed: () async {
await authModule.logout();
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => LoginScreen()),
);
},
);
},
),
],
),
);
}
}
Next, let's setup our main.dart
:
void main() {
// Create the store
final store = Store();
// Register modules
CounterModule(store);
AuthModule(store);
// Provide store to whole application
runApp(StoreProvider(
store: store,
child: ExampleApp(),
));
}
class ExampleApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: LoginScreen(),
);
}
}
And we are done! Let's check it out:
You can view the whole project here.
Thanks for reading, don't forget to check out the package!
Top comments (0)