Skip to content
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

[Blazor] Prevent Rerender component when event occured #21088

Closed
julienGrd opened this issue Apr 22, 2020 · 5 comments
Closed

[Blazor] Prevent Rerender component when event occured #21088

julienGrd opened this issue Apr 22, 2020 · 5 comments
Assignees
Labels
area-blazor Includes: Blazor, Razor Components question
Milestone

Comments

@julienGrd
Copy link

Hello guys, a notice a behavior when i use event like keydown or keyup on a table for example, it make the component re-rendering each time event occured.

Most of a time, this behavior has no incidence but on a table full of data, it can make the performance really bad.

For example, if i suscribed on a keyup event on a table, to listen for example only the arrow up and the arrow down to have keyboard selection, it will make the reload each time i write on my keyboard

  • for all key except arrow down and arrow up, nothing is expected so there is no need to reload the table
  • even for these keys, at the end only 2 rows need to change, the one become unselected and the one become selected. No need to reload all the table.

I read on the microsoft docs this is by design (i don't have the url but was something like "no need to call StateHasChanged on the event because the component will be automatically rerender")

I don't know if there is something to prevent this behavior, if not something like @onkeyup:noreload="true" would be perfect

thanks !

@javiercn javiercn added the area-blazor Includes: Blazor, Razor Components label Apr 22, 2020
@julienGrd julienGrd changed the title [Blazor] Prevent Rerenderind component when event occured [Blazor] Prevent Rerender component when event occured Apr 22, 2020
@javiercn
Copy link
Member

@julienGrd thanks for contacting us.

  • even for these keys, at the end only 2 rows need to change, the one become unselected and the one become selected. No need to reload all the table.

Blazor will minify the changes to the DOM and you can further narrow this down by using @key in the list of table rows.

I don't know if there is something to prevent this behavior

You can override ShouldRender to control this behavior, by returning true or false when called. For example, you can have a boolean that keeps track of it, set it to false when this event happens and unconditionally set it to true inside ShouldRender (which will be called as part of StateHasChanged`) to determine if the render needs to take place.

That way you achieve the behavior where it can get turned off for individual events.

@julienGrd
Copy link
Author

Thanks for your reply @javiercn

Blazor will minify the changes to the DOM and you can further narrow this down by using @key in the list of table rows

I doesnt know this directive, its a really good idea !
However it seem not work in my test (or i don't understand). I try in a generic Grid when I render rows

<table class="table table-sm table-borderless"  id="@Id" tabindex="0" @onkeyup="@OnKeyUp" @onkeyup:preventDefault @onkeyup:stopPropagation>
...
@foreach (var element in GetOrderedItems(Items))
            {
                <CascadingValue Value="this" IsFixed="true">
                    <GridRow @key="element" Element="element"></GridRowV1>
                </CascadingValue>
               
            }

i log into the afterrender of my GridRow the hashcode of my element (which is the key)

when the onkeyup event is fire all my rows are re-rendered (on the log we see the hashcode of the object doesn't change)

I can provide a reproducing example if you wan't

You can override ShouldRender to control this behavior, by returning true or false when called. For example, you can have a boolean that keeps track of it, set it to false when this event happens and unconditionally set it to true inside ShouldRender (which will be called as part of StateHasChanged`) to determine if the render needs to take place.

I don't really understand how i can achieve that ?
it's true i can make something like that

bool _needReload = true;
protected void OnKeyUp(KeyboardEventArgs args)
        {
_needReload = false;
}

protected override bool ShouldRender()
{
   return _needReload
}

but at which time i can put my boolean back to true ? whats happen if a parameter change during this boolean is setted to false ?

@mkArtakMSFT
Copy link
Member

As a side note, this may be something relevant: #18919

@mrlife
Copy link
Contributor

mrlife commented Jun 8, 2020

@julienGrd

but at which time i can put my boolean back to true ? whats happen if a parameter change during this boolean is setted to false ?

Something like this should work:

protected override bool ShouldRender()
{
    if (_needReload)
    {
        return true;
    }
    else
    {
        _needReload = true;
        return false;
    }
}

@ghost
Copy link

ghost commented Aug 8, 2020

Thank you for contacting us. Due to a lack of activity on this discussion issue we're closing it in an effort to keep our backlog clean. If you believe there is a concern related to the ASP.NET Core framework, which hasn't been addressed yet, please file a new issue.

This issue will be locked after 30 more days of inactivity. If you still wish to discuss this subject after then, please create a new issue!

@ghost ghost closed this as completed Aug 8, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Sep 7, 2020
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-blazor Includes: Blazor, Razor Components question
Projects
None yet
Development

No branches or pull requests

4 participants