Unexpected behavior when using @ref method group in callback instead of lambda #64449
-
|
I'm sure that I might be doing something wrong here since I'm not in any way a Blazor expert, but I encountered something I consider a bit unexpected. I noticed that I get an exception ( i.e., This fails when clicking the <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
<button class="btn btn-primary" @onclick="_myComponentRef.ShowComponent">MyComponent</button>But this succeed when clicking the <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
<button class="btn btn-primary" @onclick="() => _myComponentRef.ShowComponent()">MyComponent</button>HOWEVER, if I first click the I've included the source code for the components below if it's any help. Counter.cs@page "/counter"
@rendermode InteractiveServer
<PageTitle>Counter</PageTitle>
<h1>Counter</h1>
<p role="status">Current count: @_currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@* This fails *@
<button class="btn btn-primary" @onclick="_myComponentRef.ShowComponent">MyComponent</button>
@* This works *@
@* <button class="btn btn-primary" @onclick="() => _myComponentRef.ShowComponent()">MyComponent</button> *@
<MyComponent @ref="_myComponentRef"></MyComponent>
@code {
private int _currentCount = 0;
private MyComponent _myComponentRef = null!;
private void IncrementCount()
{
_currentCount++;
}
protected override void OnInitialized()
{
_myComponentRef = new MyComponent();
base.OnInitialized();
}
}MyComponent.cs@if (Show)
{
<h3>MyComponent</h3>
}
@code {
public bool Show { get; set; }
public void ShowComponent()
{
Show = true;
}
} |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 3 replies
-
|
The reason the method-group version blows up is simple: when you write Blazor tries to bind that delegate immediately, during render. It wants a real, fully initialized component reference at that exact moment. But your The lambda version: doesn’t get evaluated at render time. It’s just a little box that Blazor stores and only opens when you click the button. By that time, the component ref has been assigned, the render handle exists, all the internals are finally awake, and everything works. Now the fun part: clicking the first button fixes everything. Why? Because calling Your is basically the smoking gun. You’re manually new-ing up a component. Blazor absolutely does not want you to do that. Components must be created by the framework so they get a render handle and lifecycle. When you create one manually, it’s missing half its organs. |
Beta Was this translation helpful? Give feedback.
The reason the method-group version blows up is simple: when you write
Blazor tries to bind that delegate immediately, during render. It wants a real, fully initialized component reference at that exact moment. But your
_myComponentRefisn’t wired up yet. The render handle for the referenced component isn’t assigned, the instance isn’t connected to the render tree, and Blazor basically goes “nope.”The lambda version:
doesn’t get evaluated at render time. It’s just a little box that Blazor stores and only opens when you click the button. By that time, the component ref has been assigned, the render…