From 3ca7235d07b112c29514fe05077383eb745519a0 Mon Sep 17 00:00:00 2001 From: neuecc Date: Thu, 9 May 2024 20:02:26 +0900 Subject: [PATCH] add doc of ReactiveProperty, close #201 --- README.md | 41 +++++++++++++++++++- src/R3.Blazor/Properties/launchSettings.json | 12 ++++++ 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 src/R3.Blazor/Properties/launchSettings.json diff --git a/README.md b/README.md index b61aef0a..5ca4577e 100644 --- a/README.md +++ b/README.md @@ -145,7 +145,46 @@ Observable.EveryValueChanged(this, x => x.Height).Subscribe(x => HeightText.Text Subjects(ReactiveProperty) --- -In R3, there are four types of Subjects: `Subject`, `ReactiveProperty`, `ReplaySubject`, and `ReplayFrameSubject`. `ReactiveProperty` corresponds to what would be a `BehaviorSubject`, but with the added functionality of eliminating duplicate values. Since you can choose to enable or disable duplicate elimination, it effectively becomes a superior alternative to `BehaviorSubject`, leading to the removal of `BehaviorSubject`. +In R3, there are four types of Subjects: `Subject`, `ReactiveProperty`, `ReplaySubject`, and `ReplayFrameSubject`. + +`Subject` is an event in Rx. Just as an event can register multiple Actions and distribute values using Invoke, a `Subject` can register multiple `Observer`s and distribute values using OnNext, OnErrorResume, and OnCompleted. There are variations of Subject, such as `ReactiveProperty`, which holds a single value internally, `ReplaySubject`, which holds multiple values based on count or time, and `ReplayFrameSubject`, which holds multiple values based on frame time. The internally recorded values are distributed when Subscribe is called. + + `ReactiveProperty` corresponds to what would be a `BehaviorSubject`, but with the added functionality of eliminating duplicate values. Since you can choose to enable or disable duplicate elimination, it effectively becomes a superior alternative to `BehaviorSubject`, leading to the removal of `BehaviorSubject`. + +Here's an example of creating an observable model using `ReactiveProperty`: + +```csharp +// Reactive Notification Model +public class Enemy +{ + public ReactiveProperty CurrentHp { get; private set; } + + public ReactiveProperty IsDead { get; private set; } + + public Enemy(int initialHp) + { + // Declarative Property + CurrentHp = new ReactiveProperty(initialHp); + IsDead = CurrentHp.Select(x => x <= 0).ToReactiveProperty(); + } +} + +// --- + +// Click button, HP decrement +MyButton.OnClickAsObservable().Subscribe(_ => enemy.CurrentHp.Value -= 99); + +// subscribe from notification model. +enemy.CurrentHp.Subscribe(x => Console.WriteLine("HP:" + x)); +enemy.IsDead.Where(isDead => isDead == true) + .Subscribe(_ => + { + // when dead, disable button + MyButton.SetDisable(); + }); +``` + +In `ReactiveProperty`, the value is updated by `.Value` and if it is identical to the current value, no notification is issued. If you want to force notification of a value even if it is the same, call `.OnNext(value)`. `ReactiveProperty` has equivalents in other frameworks as well, such as [Android LiveData](https://developer.android.com/topic/libraries/architecture/livedata) and [Kotlin StateFlow](https://developer.android.com/kotlin/flow/stateflow-and-sharedflow), particularly effective for data binding in UI contexts. In .NET, there is a library called [runceel/ReactiveProperty](https://github.com/runceel/ReactiveProperty), which I originally created. diff --git a/src/R3.Blazor/Properties/launchSettings.json b/src/R3.Blazor/Properties/launchSettings.json new file mode 100644 index 00000000..52eb2da6 --- /dev/null +++ b/src/R3.Blazor/Properties/launchSettings.json @@ -0,0 +1,12 @@ +{ + "profiles": { + "R3.Blazor": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:57917;http://localhost:57918" + } + } +} \ No newline at end of file