Flutter Super State: Simple State Management for Flutter
Tags: flutter, dart, statemanagement
Published: 2020-05-07 22:53:24

---
title: Flutter Super State: Simple State Management for Flutter
published: true
description: A simple state management library for Flutter (with async support). Guiding you through setting up a sample application.
tags: Flutter,Dart,State-Management
---

[flutter_super_state](https://pub.dev/packages/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:

```dart
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:

```dart
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:

```dart
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 calls `setState`)
- `StoreBuilder`: Access the store inside the Flutter widget tree (is updated when any module calls `setState`)

## Example

Let's start by creating a new project using `flutter create super_state_example` and adding the package to `pubspec.yaml`:

```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`):

```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`):

```dart
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`:

```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:

{% youtube HEG2EwqCSkY %}


You can view the [whole project here](https://github.com/Cretezy/flutter_super_state_example).

Thanks for reading, don't forget to [check out the package](https://pub.dev/packages/flutter_super_state)!