I am having a hard time understanding when I should call StateHasChanged()
and when Blazor intercepts that something is changed so it must be re-rendered.
I've created a sample project with a button and a custom component called AddItem. This component contains a div with a red border and a button.
What I expected: I want that the AddItem's div will show up when the user clicks on the button contained inside the Index page. Then I want to hides it when the user clicks on AddItem's button.
Note: AddItem doesn't expose it _isVisible
flag outside, instead it contains a Show()
method. So AddItems.Show()
will be invoked when the Index's button is clicked.
Tests:
I click on Index's click button then the methods
Open()
andAddItem.Show()
are invoked. The flag_isVisible
is set totrue
but nothing happens and Index'sShouldRender()
is invoked.Console output:
- Render Index
I've modified
AddItem.Show()
withpublic void Show() {_isVisible = true; StateHasChanged();}
. Now the AddItem's div shows and hide as expected.Console output:
- Render AddItem (1° click on index's button)
- Render Index (1° click on index's button)
- Render AddItem (2° click on addItem's close button)
I've modified
<AddItem @ref="AddItem" />
with<AddItem @ref="AddItem" CloseEventCallback="CallBack" />
, removedStateHasChanged
from AddItem'sShow()
method. Now the AddItem's div shows and hides as expected.
Based on Test 3: Why I don't have to explicit
StateHasChanged
if I set AddItem'sCloseEventCallback
to any parent's method? I'm having a hard time understanding it because AddItem doesn't invokeCloseEventCallback
anywhere.
and
When Blazor understands that something is changed so it must be re-render?
My sample code (if you want to try it).
My Index.razor
<AddItem @ref="AddItem" />
<button @onclick="Open">click</button>
@code {
AddItem AddItem;
public void Open()
{
AddItem.Show();
}
public void CallBack()
{
}
protected override bool ShouldRender()
{
Console.WriteLine("Render INDEX");
return base.ShouldRender();
}
}
My AddItem component
@if (_visible)
{
<div style="width: 100px; height: 100px; border: 1px solid red">testo</div>
<button @onclick="Close">close</button>
}
@code {
private bool _visible = false;
[Parameter] public EventCallback<bool> CloseEventCallback { get; set; }
public void Show()
{
_visible = true;
}
public void Close()
{
_visible = false;
}
protected override bool ShouldRender()
{
Console.WriteLine("Render ADDITEM");
return base.ShouldRender();
}
}