From 60c5aa71a57a67be02bee80311b7c6bd126f78b1 Mon Sep 17 00:00:00 2001 From: Kartal Kaan Bozdogan Date: Mon, 25 Dec 2023 11:44:07 +0100 Subject: [PATCH] effect docs --- README.md | 18 ++++++++++++++---- example/example.dart | 2 +- example/temporal_accumulator.dart | 9 ++++----- example/temporal_difference.dart | 9 ++++----- example/todo.dart | 6 +++--- 5 files changed, 26 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index eb685d5..13a26c4 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ Computed: - [Here is how it works](#here-is-how-it-works) - [A larger example](#a-larger-example) +- [Effects](#effects) - [Testing](#testing) - [Looking at the past](#looking-at-the-past) - [Computed queries](#computed-queries) @@ -65,10 +66,7 @@ Assume for the sake of example that your business logic is to multiply the recei Here is how you can do this using Computed: ``` -final c = $(() => s.use * 2); -final sub = c.asStream.listen((res){ - db.write(res); -}); +$(() => s.use * 2).asStream.listen(db.write); ``` That's it. Computed will take care of re-running the computation and calling the listener as needed. Note how you did not need to specify a dependency list for the computation, Computed discovers it automatically. You don't even have any mutable state in your app code. @@ -141,6 +139,18 @@ $(() { }).asStream.listen(db.write); ``` +## Effects + +Effects allow you to define computations with side effects. Like `.listen` and getters which convert computations to data sources (such as `.asStream`), effects ultimately trigger the computation graph. +Effects are particularly useful if you wish to define side effects depending on multiple data sources or computations: + +``` +Stream activePage; +Stream isDarkMode; + +Computed.effect(() => sendAnalytics(activePage.use, isDarkMode.use)); +``` + ## Testing Computed lets you mock any computation or data source, allowing you to easily test downstream behaviour. diff --git a/example/example.dart b/example/example.dart index b422b1c..d42718a 100644 --- a/example/example.dart +++ b/example/example.dart @@ -17,7 +17,7 @@ void main() async { return maybeReversed.use.rebuild((p0) => p0.add(0)); }); - append0.listen((value) => print(value), () => print('Exception!')); + Computed.effect(() => print(append0.use)); // ignore: unused_local_variable final unused = $(() { diff --git a/example/temporal_accumulator.dart b/example/temporal_accumulator.dart index 20b52b6..591adbf 100644 --- a/example/temporal_accumulator.dart +++ b/example/temporal_accumulator.dart @@ -5,14 +5,13 @@ import 'package:computed/computed.dart'; void main() async { final cont = StreamController.broadcast(sync: true); final s = cont.stream; - Computed.withPrev((prev) { + final c = Computed.withPrev((prev) { var res = prev; s.react((val) => res += val); return res; - }, initialPrev: 0) - .listen((event) => print(event), (e) { - print('Exception: $e'); - }); + }, initialPrev: 0); + + Computed.effect(() => print(c.use)); await Future.value(); cont.add(1); diff --git a/example/temporal_difference.dart b/example/temporal_difference.dart index bb32c59..ec53204 100644 --- a/example/temporal_difference.dart +++ b/example/temporal_difference.dart @@ -5,15 +5,14 @@ import 'package:computed/computed.dart'; void main() { final cont = StreamController.broadcast(sync: true); final s = cont.stream; - $(() { + final c = $(() { s.use; // Make sure it has a value late int res; s.react((val) => res = val - s.prevOr(0)); return res; - }, memoized: false) - .listen((event) => print(event), (e) { - print('Exception: $e'); - }); + }, memoized: false); + + Computed.effect(() => print(c.use)); cont.add(1); cont.add(1); diff --git a/example/todo.dart b/example/todo.dart index fa90ce4..313f462 100644 --- a/example/todo.dart +++ b/example/todo.dart @@ -81,10 +81,10 @@ void main() async { (prev) => Tuple2(prev == null, appState.use), initialPrev: null); - stateIsInitial.listen((state) { + Computed.effect(() { // Do not save the initial state - if (!state!.item1) db.saveState(state.item2); - }, (e) => print('Exception: ${e.toString()}')); + if (!stateIsInitial.use!.item1) db.saveState(stateIsInitial.use!.item2); + }); uiCreateController.add('new todo'); await Future.delayed(Duration.zero);