-
-
Notifications
You must be signed in to change notification settings - Fork 106
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Suggestion: R3 signals (ReactiveProperty++) #283
Comments
Thank you for the suggestion. Since I don't think this should be a core functionality, I believe it would be better to keep it as an external extension that people can optionally use if they want to. |
Yes probably you are right about the external extension. With ReactiveProperties and ReadOnlyReactiveProperty you can do everything, sometimes can be less readable and more difficult. I created a small comparison: Signalspublic class ExampleWithSignals
{
public ExampleWithSignals()
{
ComputedFromName = Signal.Computed(() => $"Computed value is {Name.Value}");
IsNameValid = Signal.AsyncComputed(async cancellationToken =>
{
var name = Name.Value;
await Task.Delay(1000, cancellationToken);
return !string.IsNullOrWhiteSpace(name);
}, false, ConcurrentChangeStrategy.CancelCurrent);
// The idea is that is signals we can execute arbitrary functions, so we can use if, switch, function calls etc
// The properties will be automatically tracked.
// Same with async functions
CanLogin = Signal.Computed(() =>
{
// If IsNameValid.IsComputing is true, we dont even subscribe to IsNameValid changes
// If IsNameValid.IsComputing is true, and IsNameValid.Value is false. we dont even subscribe to Password changes
if (IsNameValid.IsComputing.Value || !IsNameValid.Value)
{
return false;
}
return !string.IsNullOrWhiteSpace(Password.Value);
});
// This is equivalent to the Signal.Computed above
// Is usefull if we want to apply some other operators before converting the observable to a signal
CanLogin = Signal.ComputedObservable(() =>
{
if (IsNameValid.IsComputing.Value || !IsNameValid.Value)
{
return false;
}
return !string.IsNullOrWhiteSpace(Password.Value);
})
.ToSignal();
}
Signal<string> Name { get; } = new("");
Signal<string> Password { get; } = new("");
IReadOnlySignal<string> ComputedFromName { get; }
IAsyncReadOnlySignal<bool> IsNameValid { get; }
IReadOnlySignal<bool> CanLogin { get; }
IReadOnlySignal<(string name, string password)> NamePasswordTuple { get; set; }
} ReactivePropertiespublic class ExampleWithReactiveProperties
{
public ExampleWithReactiveProperties()
{
ComputedFromName = Name.Select(x => $"Computed value is {x}")
.ToReadOnlyReactiveProperty("");
IsNameValid = ComputedFromName.SelectAwait(async (name, cancellationToken) =>
{
IsNameValidIsExecuting.Value = true;
try
{
await Task.Delay(1000, cancellationToken); // simulate som
return !string.IsNullOrWhiteSpace(name);
}
finally
{
IsNameValidIsExecuting.Value = false;
}
}, AwaitOperation.Switch).ToReadOnlyReactiveProperty();
// Here I am trying to reproduce exactly what copmuted signals do
// Of course this is not how I would write this logic without signals :)
CanLogin = IsNameValidIsExecuting.Select(isExecuting => isExecuting switch
{
true => Observable.Return(false),
false => IsNameValid.Select(isNameValid => isNameValid switch
{
false => Observable.Return(false),
true => Password.Select(p => !string.IsNullOrWhiteSpace(p))
}).Switch()
}).Switch()
.ToReadOnlyReactiveProperty();
}
ReactiveProperty<string> Name { get; } = new("");
ReactiveProperty<string> Password { get; } = new("");
ReadOnlyReactiveProperty<string> ComputedFromName { get; }
ReadOnlyReactiveProperty<bool> IsNameValid { get; }
ReactiveProperty<bool> IsNameValidIsExecuting { get; } = new(false);
ReadOnlyReactiveProperty<bool> CanLogin { get; }
} |
Hey!
I love this rebirth of Rx and everything you did in this repo.
I was wondering if angular signals could be a good addition for this library.
Signals are pretty much the same a ReactiveProperties, but with the (huge) plus of automatically recompute the value based on other properties (Computed signals).
I already created a possible implementation based completely on R3, and I think its great.
Maybe could be integrated here? What you think?
Thank you!
The text was updated successfully, but these errors were encountered: