Closed peterhym21 closed 1 year ago
@peterhym21
The HotKeys2
doesn't accept functions that return a Task
. This is by design. Please use functions that return a ValueTask
instead, like this:
async ValueTask Cancel() => await BlazoredModal.CancelAsync();
// 👆 Use `ValueTask` instead of `Task`.
Hi @jsakamoto
Thanks for the help, but I don't understand why this is by design can you maybe clarify and help me to fined a better solution for my problem? In advance thanks :)
Because now you cant use it in with a Task Like async Task OK() => await BlazoredModal.CloseAsync();
witch is a existing method for a Button. so u have to make a new method for just the HotKey
see below for old and new HotKeys versions code that I am talking about
Old Hotkeys
@inject HotKeys HotKeys
@implements IDisposable
<div class="modal ">
<div class="modal-content bg-danger">
<div class="modal-header">
<h3 class="modal-title">Error</h3>
</div>
<div class="modal-body">
<p class="message">@Message</p>
</div>
<div class="modal-footer">
<RadzenButton Click="OK" ButtonStyle="ButtonStyle.Primary" class="modal-button">OK</RadzenButton>
<RadzenButton Click="Cancel" ButtonStyle="ButtonStyle.Light" class="modal-button">Cancel</RadzenButton>
</div>
</div>
</div>
@code {
[CascadingParameter] BlazoredModalInstance BlazoredModal { get; set; } = default!;
[Parameter] public string? Message { get; set; }
HotKeysContext? HotKeysContext;
protected override async Task OnInitializedAsync()
{
this.HotKeysContext = this.HotKeys.CreateContext()
.Add(ModKeys.None, Keys.ESC, Cancel);
}
async Task OK() => await BlazoredModal.CloseAsync();
async Task Cancel() => await BlazoredModal.CancelAsync();
public void Dispose() => this.HotKeysContext.Dispose();
}
New HotKeys2
@inject HotKeys HotKeys
@implements IDisposable
<div class="modal ">
<div class="modal-content bg-danger">
<div class="modal-header">
<h3 class="modal-title">Error</h3>
</div>
<div class="modal-body">
<p class="message">@Message</p>
</div>
<div class="modal-footer">
<RadzenButton Click="OK" ButtonStyle="ButtonStyle.Primary" class="modal-button">OK</RadzenButton>
<RadzenButton Click="Cancel" ButtonStyle="ButtonStyle.Light" class="modal-button">Cancel</RadzenButton>
</div>
</div>
</div>
@code {
[CascadingParameter] BlazoredModalInstance BlazoredModal { get; set; } = default!;
[Parameter] public string? Message { get; set; }
HotKeysContext? HotKeysContext;
protected override async Task OnInitializedAsync()
{
this.HotKeysContext = this.HotKeys.CreateContext()
.Add(ModCode.None, Code.Escape, CancelHotkey);
}
async Task OK() => await BlazoredModal.CloseAsync();
async Task Cancel() => await BlazoredModal.CancelAsync();
async ValueTask CancelHotkey() => await BlazoredModal.CancelAsync();
public void Dispose() => this.HotKeysContext.Dispose();
}
Hi @peterhym21,
why this is by design
The first reason is "performance". ValueTask
is a struct, not a class, so it doesn't need to be allocated from the heap area. That means ValueTask
never causes garbage collection. This is important, particularly in the Blazor WebAssembly scenario, because usually, Blazor WebAssembly is driven by MSIL interpreter, not native processor speed.
See also: "ValueTask vs. Task" https://medium.com/@karol.rossa/valuetask-vs-task-5fb4f9c6517
The second reason is that I don't want to spend much time implementing the HotKeys2
library. If I'm implementing Task
support, I will need a lot of time to implement many Add
methods of overload versions and unit tests to test them. Currently, I've wanted to keep working on another of my hobby product.
Those are reasons "why this is by design".
By the way, if you must the callback method be a Task
async method, you can use it by the following syntax.
...
@code {
...
protected override async Task OnInitializedAsync()
{
this.HotKeysContext = this.HotKeys.CreateContext()
// Wrap your `Task` async method with 👇 async/await lambda like below.
.Add(ModCode.None, Code.Escape, async () => await Cancel());
}
...
async Task Cancel() => await BlazoredModal.CancelAsync();
...
Moreover, you can also implement your custom extension Add
method, which accepts a Task
async method by yourself.
P.S.
There are Add
methods overload versions that don't have a ModCode
or a ModKey
argument. For example, if the ModCode
argument is None
like this:
.Add(ModCode.None, Code.Escape, async () => await Cancel());
You can rewrite it shorter without the ModCode
argument like below:
.Add(Code.Escape, async () => await Cancel());
Happy Coding!
When trying to use is with a async task it does not work:
gives these errors
works fine if I use a void method
@jsakamoto any help?