How to avoid a mass rerendering of everything that depends on only unchanged parts of a State object?
See original GitHub issueAnytime a handler mutates the state, any component that gets state properties and inherits from BlazorStateComponent
will automatically rerender. Right?
So that means that any component that depends on one part of that state but not another part will still rerender regardless of what part of the state they need. In other words, if my component shows MyState.A
but not MyState.B
, and there is a change to MyState.B
, my component will rerender even though it doesn’t need to.
Suppose I enable a rather complex domain object to be edited piecemeal. So the user might edit a CommentsPanel
that internally uses CurrentOrderState.OrderComments
and a RushShippingPanel
that internally uses CurrentOrderState.IsRushShipping
, along with dozens of other properties. So now any change anywhere in the state will result in dozens of components being rerendered when it is more desirable that only one part at a time needs to be rerendered. Is there any way to get more granular with rerendering of components that inherit from BlazorStateComponent
? It strikes me that rerendering everything that depends on a state object when anything in that state object changes (because it’s a whole new state each time) is a very blunt approach.
I am thinking there should be a way to avoid rerendering for unchanged parts of the state, as it is inevitable that even the simplest properties on a state object will themselves have properties, many of which won’t change.
Side note: I am using the term “rerender” for the process by which .NET (in WebAssembly) runs the C# code to figure out the overall presentation state of each component in memory. After that, OnAfterRender
is called, then manipulating the DOM is a subsequent process. I try to avoid using the term “render” to mean “manipulating the DOM”, since it seems Microsoft uses it to mean running the C# code.
For pages of significant scope, rerendering can be the source of much slowness. If I am showing a 30x10 cell table, and each cell has 1-3 components in it, it can be quite burdensome to rerender (run the C# code to determine what the DOM should become) hundreds of components. So it would be nice if there was a way to avoid rerendering a component if the parts of the state it depends on have not changed. I have written a small package to do this apart from state management, but I was hoping that changes due to state management wouldn’t need such a thing (nor do I see a way to make them collaborate together).
Vue and React seem to automagically handle this (I think internally they compare previous state to new state on a per-property basis), but not so with Blazor (hence the need for StateHasChanged at all).
Issue Analytics
- State:
- Created 2 years ago
- Reactions:1
- Comments:9 (4 by maintainers)
Top GitHub Comments
Suppose I have a single-page app that might want state management to store the possible filter values for each of serveral fields in an advanced search, and the current value of each field, and the current search results, and the currently selected item in the search results, and whether that item’s detail is currently being shown. One component might show several of these pieces and another compnoent will show some of them as well as others. I think you would suggest I break up this into several state classes, and I agree…but it would be quite nice to have a single master state object where I can use Intellisense to find what I want in the state, so I can just reference what I want, e.g. getting State.Filters.DateRange.AllValues or State.SearchResults.First() or State.SearchResults[42].IsSelected or State.CurrentItem.IsOpen.
Now for example, say I have an action that toggles a boolean on one of the search results, (State.SearchResults[42].IsSelected) and the only thing in the whole state that renders differently based on that boolean value is one component in the several dozen used to show that component.
Ideally, any change to the state would not cause a rerender of thousands of components I am showing nor even the dozens for this item, but only the one that actually shows a check mark or a frowny face for State.SearchResults[42].IsSelected’s value. Ideally, I want to specify it at any level down the tree of objects in the state. so that other components used to show the items in the collection don’t rerender.
As discussed on Discord, here’s a minimal demo of the rerendering issue #266 that I would like to help make nuanced: https://szalapski.github.io/BlazorRerenderReducers/blazor-state-demo And here’s the code: https://github.com/szalapski/BlazorRerenderReducers/tree/main/Sz.BlazorRerenderReducers/Client/BlazorStateDemo