Blazor Components
Each .razor file (+ partial classes) is a component- and invisibly inherits ComponentBase : IComponent. You can @inherits from another base class than inherits from ComponentBase.
Layouts inherit LayoutComponentBase and have a @Body parameter. Apply a layout with @layout name (overrides router's RouteView DefaultLayout). A folder with an _imports.razor can have a @layout that applies to all components in the folder.
You can also @implements IDisposable or @implements IAsyncDisposable (but not both!) - things like events and js interop.
Prefer using .razor.cs partial classes for code alongside the .razor, avoid @code blocks. NB: @using and using statements are different.
You can also use standard generic C# instead of @typeparam TMyType
You can @inherit MyBaseComponent but it doesn't inherit razor markup- only the @code. Instead use RenderFragment or simple wrapping.
//don't do this, this is a partial class, so add x.razor.cs
[Parameter]
public string? Name { get; set; }
}
namespace BlazorApp.Client.Shared;
//better: partial class with your code separate from markup
public partial class UserName
{
[Parameter]
public string? Name { get; set; }
}
You can use an ILogger, but in WASM it is just to browser devtools/F12. There is no Application Insights for blazor client side. Finding client side exceptions is tough, but perhaps a component with an httpClient to send the stack to the server might help...
Lifecycle
This component shows a list of the lifecycle events- SetParametersAsync, OnInitialized and OnParametersSet.
OnAfterRender should not appear (because it finished rendering!) unless we notify that StateHasChanged() as done here!
<ul>
@foreach (var e in LifeCycleEvents)
{
<li>@e</li>
}
</ul>
@code {
public IList<string> LifeCycleEvents { get; set; } = new List<string>();
//lifecycle in order
public override async Task SetParametersAsync(ParameterView parameters)
{
//sets the parameters
await base.SetParametersAsync(parameters);
LifeCycleEvents.Add("SetParametersAsync");
}
protected override void OnInitialized()
{
//this (or the async version) is the OnLoad for most startup logic
LifeCycleEvents.Add("OnInitialized");
}
//or async version
// protected override async Task OnInitializedAsync()
// {
// await ...
// }
protected override void OnParametersSet()
{
LifeCycleEvents.Add("OnParametersSet");
}
protected override void OnAfterRender(bool firstRender)
{
LifeCycleEvents.Add("OnAfterRender " + firstRender);
Logger.LogInformation("Too late, already rendered, but this appears in F12 devtools");
//you can make it appear by changing state
if (firstRender) StateHasChanged();
}
}
Each component (including eg form components like InputText) can have a @ref- you use this as the id.