Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/ensody/reactive_state
An easy to understand reactive state management solution for Flutter.
https://github.com/ensody/reactive_state
dart flutter flutter-package flutter-plugin mobile mobile-development observable observer-pattern state state-management
Last synced: 7 days ago
JSON representation
An easy to understand reactive state management solution for Flutter.
- Host: GitHub
- URL: https://github.com/ensody/reactive_state
- Owner: ensody
- License: mit
- Created: 2019-07-24T11:16:39.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2020-04-01T09:13:39.000Z (over 4 years ago)
- Last Synced: 2024-10-14T09:25:51.976Z (about 1 month ago)
- Topics: dart, flutter, flutter-package, flutter-plugin, mobile, mobile-development, observable, observer-pattern, state, state-management
- Language: Dart
- Homepage: https://pub.dev/packages/reactive_state
- Size: 110 KB
- Stars: 18
- Watchers: 4
- Forks: 2
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# reactive_state
[![Pub](https://img.shields.io/pub/v/reactive_state.svg)](https://pub.dev/packages/reactive_state)
[![Build Status](https://travis-ci.com/ensody/reactive_state.svg?branch=master)](https://travis-ci.com/ensody/reactive_state)An easy to understand reactive state management solution for Flutter.
## Principles
### Observable state
State is held in one or multiple instances of `Value` or similar classes implementing `ValueNotifier`.
These are standard Flutter interfaces that everybody knows from `TextEditingController`, `Animation`, etc.Additionally, you can use `ListValue` and `MapValue` for creating observable `List` and `Map` values that can notify you about fine-grained change events (instead of the whole value changing).
### Reactive widgets
`AutoBuild` automatically rebuilds your widgets when a `ValueNotifier` (or any `Listenable`) triggers a notification. It's similar to Flutter's `ValueListenableBuilder`, but it can track multiple dependencies and also works with `Listenable`.
No need to call `addListener`/`removeListener`. Just `get()` the value directly while `AutoBuild` takes care of tracking your dependencies.
Unlike `InheritedWidget` and `Provider` you get fine-grained control over what gets rebuilt.
Standard Flutter classes like `TextEditingController` and `Animation` implement `ValueListenable` and thus work nicely with `AutoBuild`.
### Derived/computed state
`DerivedValue` is an observable value that is computed (derived) from other observable values.
Also, `ListValue` and `MapValue` provide `.map()` and other operations for creating derived containers that keep themselves updated on a per-element basis.
### Less boilerplate and indirection
The resulting code is much simpler than the same solution in [BLoC](https://www.didierboelens.com/2018/08/reactive-programming---streams---bloc/) or Redux.
* No streams, no `StreamBuilder`, no asynchronous loading of widgets (unless you really need it).
* No special event objects, no event handlers with long `switch()` statements.## Usage
Note: Also see [reference](https://pub.dev/documentation/reactive_state/latest/) for details.
A simple `AutoBuild` example:
```dart
import 'package:flutter/material.dart';
import 'package:reactive_state/reactive_state.dart';class MyPage extends StatelessWidget {
MyPage({Key key, @required this.counter}) : super(key: key);final ValueNotifier counter;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Counter')),
body: Column(
children: [
AutoBuild(builder: (context, get, track) {
return Text('Counter: ${get(counter)}');
}),
MaterialButton(
onPressed: () => counter.value++,
child: Text('Increment'),
),
],
),
);
}
}
```Note that in real-world applications you shouldn't directly mutate the state, but instead put that into separate methods e.g. on an object made accessible through the [provider](https://pub.dev/packages/provider) package.
Also, take a look at the [example](https://github.com/ensody/reactive_state/blob/master/example/lib/main.dart) in the repo.
## autoRun and AutoRunner
Outside of widgets you might still want to react to state changes.
You can do that with `autoRun()` and `AutoRunner` (see [reference](https://pub.dev/documentation/reactive_state/latest/) for details).## Value vs ValueNotifier
As an alternative to `ValueNotifier` you can also use `reactive_state`'s `Value` class which provides an `update()` method for modifying more complex objects:
```dart
class User {
String name = '';
String email = '';
// ...
}var userValue = Value(User());
userValue.update((user) {
user.name = 'Adam';
user.email = '[email protected]';
});
```This is similar to calling `setState()` with `StatefulWidget`.
With `update()` you can change multiple attributes and `Value` will trigger a single notification once finished - even if nothing was changed (so you don't need to implement comparison operators for complex objects).## DerivedValue
`DerivedValue` is a dynamically calculated `ValueListenable` that updates its value whenever its dependencies change:
```dart
var user = Value(User());
var emailLink = DerivedValue((get, track) => 'mailto:${get(user).email}');
```Here, `emailLink` can be observed on its own and is updated whenever `user` is modified.
## ListValue and MapValue
A simple example showing a few things that can be done:
```dart
final listValue = ListValue([]);
final mappedList = listValue.map((x) => x.toString());
final listToMap = mappedList.toMap((x) => MapEntry(2 * int.parse(x), x));
final invertedMap = listToMap.map((k, v) => MapEntry(v, k));listValue.addAll([4, 1]);
// => invertedMap.value == {'4': 8, '1': 2}
```