reactive_state 0.7.0-dev.1 copy "reactive_state: ^0.7.0-dev.1" to clipboard
reactive_state: ^0.7.0-dev.1 copied to clipboard

An easy to understand reactive state management solution for Flutter.

example/lib/main.dart

// This is a simple, but pretty complete reactive_state example.
// It demonstrates use-cases for small and large apps:
//
// Actions & state values can be globally accessible via Provider.
// This can be useful for making e.g. the currently logged-in user accessible
// from anywhere in the app.
//
// Actions & state values can alternatively be passed directly as arguments.
// This is important for writing reusable components that mustn't depend on
// some globally accessible app-specific state.

import 'package:flutter/material.dart';
import 'package:reactive_state/reactive_state.dart';
import 'package:provider/provider.dart';

void main() => runApp(App());

class User {
  User({this.name = '', this.email = '', this.location = ''});

  String name;
  String email;
  String location;
}

// Global state that the whole app has access to via a Provider.
// For complex apps you might want to split this up into multiple classes
// that cleanly take care of orthogonal state & action aspects.
class GlobalState {
  // We use Value instead of ValueNotifier because we need the update() helper below.
  final user = Value<User>(User());

  // A globally reachable action that is potentially used in multiple places.
  void updateUser(String name, String email) {
    // This demonstrates the Value.update() helper
    user.update((u) {
      u.name = name;
      u.email = email;
    });
  }
}

// We use a StatefulWidget to retain the state between hot reloads
class App extends StatefulWidget {
  @override
  _AppState createState() => _AppState();
}

class _AppState extends State<App> {
  // Global state that will be available in the whole app.
  final state = GlobalState();

  // Local state that is only accessible to a subsection of the app.
  // If you have to pass lots of these objects as arguments *and* if they
  // conceptually belong together, you might want to group them in classes like
  // we did with GlobalState and pass a whole group as a single argument.
  final counter = ValueNotifier<int>(0);

  // A local action that is potentially used in multiple places, but only
  // needed in a subsection of your app.
  void decrement() {
    counter.value--;
  }

  @override
  Widget build(BuildContext context) {
    // We use a MultiProvider, so we can easily add more state objects later
    return MultiProvider(
      providers: [Provider.value(value: state)],
      child: MaterialApp(
        title: 'reactive_state example',
        home: HomePage(counter: counter, decrement: decrement),
      ),
    );
  }
}

class HomePage extends StatelessWidget {
  HomePage({Key key, @required this.counter, @required this.decrement})
      : super(key: key);

  final ValueNotifier<int> counter;
  final VoidCallback decrement;
  final nameController = TextEditingController();
  final emailController = TextEditingController();

  void _saveUser(GlobalState globalState) {
    globalState.updateUser(nameController.text, emailController.text);
  }

  @override
  Widget build(BuildContext context) {
    final globalState = Provider.of<GlobalState>(context);

    return Scaffold(
      appBar: AppBar(
        title: Text('Edit values'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('Counter (press "+"/"-" buttons):'),
            // We use multiple AutoBuild widgets to minimize redrawing.
            AutoBuild(builder: (context, get, track) {
              return Text('${get(counter)}');
            }),
            SizedBox(height: 20),
            Text('User data'),
            AutoBuild(builder: (context, get, track) {
              var user = get(globalState.user);
              return Column(
                mainAxisSize: MainAxisSize.min,
                children: <Widget>[
                  Text('Name: ${user.name}'),
                  Text('Email: ${user.email}'),
                ],
              );
            }),
            Container(
              constraints: BoxConstraints(
                  maxWidth: MediaQuery.of(context).size.width * 0.7),
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: <Widget>[
                  TextFormField(
                    decoration: InputDecoration(hintText: 'Name'),
                    controller: nameController,
                    textCapitalization: TextCapitalization.words,
                    keyboardType: TextInputType.text,
                  ),
                  TextFormField(
                    decoration: InputDecoration(hintText: 'Email'),
                    controller: emailController,
                    autocorrect: false,
                    keyboardType: TextInputType.emailAddress,
                  ),
                ],
              ),
            ),
            AutoBuild(builder: (context, get, track) {
              var enabled = get(nameController).text.isNotEmpty &&
                  get(emailController).text.isNotEmpty;
              var onPressed = enabled ? () => _saveUser(globalState) : null;
              return MaterialButton(
                onPressed: onPressed,
                child: Text('Save'),
              );
            })
          ],
        ),
      ),
      floatingActionButton: Column(
        crossAxisAlignment: CrossAxisAlignment.end,
        mainAxisAlignment: MainAxisAlignment.end,
        children: <Widget>[
          Padding(
            padding: EdgeInsets.symmetric(vertical: 5.0),
            child: FloatingActionButton(
              child: Icon(Icons.add),
              // Demonstrating trivial update case
              onPressed: () => counter.value++,
            ),
          ),
          Padding(
            padding: EdgeInsets.symmetric(vertical: 5.0),
            child: FloatingActionButton(
              child: Icon(Icons.remove),
              // Demonstrating reusable action via callback
              onPressed: decrement,
            ),
          ),
        ],
      ),
    );
  }
}
1
likes
40
points
18
downloads

Publisher

verified publisherensody.com

Weekly Downloads

An easy to understand reactive state management solution for Flutter.

Repository (GitHub)

License

MIT (license)

Dependencies

flutter

More

Packages that depend on reactive_state