- ABP Framework version: v8.3.2
- UI Type: Blazor WASM
- Database System: EF Core (SQL Server)
- Tiered (for MVC) or Auth Server Separated (for Angular): no
- Steps to reproduce the issue:
- Creating an ABP solution (v.8.3.2 Blazor WASM)
- Follow the guide: https://abp.io/docs/latest/framework/ui/blazor/toolbars#example-add-a-notification-icon to create a component and add it to the toolbar.
Dear Support Team,
I am working on an ABP project using version 8.3.2 with a Blazor WASM frontend. I followed your guide to customize the toolbar and add my own component Specifically, I created a class implementing IToolbarContributor, added my component to toolbar.Items, and configured the toolbar in BlazorClientModule.
However, I have noticed that the initialization of the component inside the toolbar is executed twice.
Could you help me understand why this is happening? Is this a bug?
The double initialization is problematic for me because, during initialization, I need to make server calls, register events, and attach to a SignalR hub, among other things. The duplicate initialization is causing unexpected issues.
Thank you for your support.
Best regards, Roberto
10 Answer(s)
-
0
Hello,
Can you send the code of the component you created?
The problem may be caused by the lifecycle of Blazor Components. See more: https://learn.microsoft.com/en-us/aspnet/core/blazor/components/lifecycle?view=aspnetcore-9.0#after-component-render-onafterrenderasync
-
0
Hi,
I modified the component in the guide to log "Notification component initialized!" when the componenent initalizes. The code is the following:
@using Microsoft.Extensions.Logging @inherits Volo.Abp.AspNetCore.Components.AbpComponentBase <div style="color: white; margin: 8px;"> <i class="far fa-bell" @onclick="ShowNotifications"></i> </div> @code { private async Task ShowNotifications() { await Message.Info("TODO: Show notifications"); } protected override Task OnInitializedAsync() { Logger.LogInformation("Notification component initialized!"); return base.OnInitializedAsync(); } }
As you can see in the following screenshot when i load in the application it prints the Log 2 times:
Same thing is noticed if you put a breakpoint onto the "Logger.LogInformation" line, it runs 2 times.
How can we fix this?
-
0
As far as I understand, the problem does not seem to be related to ABP. I found a content like below in ASP.NET's Blazor documentation:
To prevent developer code in OnInitializedAsync from running twice when prerendering, see the Stateful reconnection after prerendering section. The content in the section focuses on Blazor Web Apps and stateful SignalR reconnection. To preserve state during the execution of initialization code while prerendering, see Prerender ASP.NET Core Razor components.
Reference: https://learn.microsoft.com/en-us/aspnet/core/blazor/components/lifecycle?view=aspnetcore-9.0#component-initialization-oninitializedasync
You can also look here on how to prevent this.
-
0
Hi,
The problem and solution you describe are not actually what is causing this problem because prerender is already set to "false" in the base ABP framework Blazor WASM project:
It seems the problem is specifically the toolbar because if i make a copy of the "Notification" component and add it to a page, the "OnInitializedAsync" function only runs once.
This is what happens when the component is in the Toolbar:
This is what happens when the component is in the Page:
Hope this clarifies the problem i'm facing.
-
0
Hi,
I assume you're using LeptonX Theme right?
In the leptonx, Desktop Toolbar and Mobile Toolbar are separated and this component is rendered twice, one for desktop toolbar and one for mobile toolbar. That's why you see 2 different logs in your console.
If you wish to use it in the only for desktop view, I suggest you to use
LeptonXToolbars.Main
orLeptonXToolbars.MainMobile
instead directly usingStandardToolbars.Main
from the framework:if (context.Toolbar.Name == LeptonXToolbars.Main) { context.Toolbar.Items.Insert(0, new ToolbarItem(typeof(Notification))); }
If you want to share a state between those 2 component instances, you can use a Singleton or Scoped service to get data from a service and keep the data in that service and render directly from that service. In that case, you'll make a single request and share data that obtained once.
-
0
Hi,
Thanks for the reply, i understand now what the issue is. I have a few questions reguarding this approach. Why would leptonX render both toolbars regardless of if im viewing the page from mobile or desktop? Wouldn't it be better perfomance wise if they only rendered when necessary? Is there an option to achieve this rather then having them both render always?
-
0
Hi,
Thanks for the reply, i understand now what the issue is. I have a few questions reguarding this approach. Why would leptonX render both toolbars regardless of if im viewing the page from mobile or desktop? Wouldn't it be better perfomance wise if they only rendered when necessary? Is there an option to achieve this rather then having them both render always?
Unfortunately it's not a programming decision. The HTML structure of the LeptonX theme requires 2 different usage since desktop toolbar and mobile toolbar has completely different html tree. It cannot change menu & toolbars only visually by using CSS. The html structure also is different and both should be added separately. That's why we have 2 different component to match leptonx html structure in blazor.
https://x.leptontheme.com/side-menu/index.html
-
0
I ask you to update the documentation by adding this clarification and an example how to avoid the problem.
Thanks
-
0
Thanks, we will review the relevant document and update it if we need to update it. I created an internal issue for this.
I'm closing this issue for now. If you have a different question, feel free to create a new question.
-
0
We've added it to the documents, for your information. See: https://github.com/abpframework/abp/pull/22218