What happens when you navigate to the "same page" in Blazor?
May 3, 2023 · 3 minute read · Tags: blazor
Sometimes you might want the same ‘page’ in your Blazor app to load for different paths.
Here’s an example of a contacts page that loads the same component for both /contacts
and /contacts/{id}
When the user clicks the link to view the ‘Alice Krige’ contact the browser will attempt to navigate to /contacts/1
.
However, Blazor will intercept this navigation and, rather then reload the entire site, simply re-render this same component with the new parameter values.
Because the Id
parameter is set to 1
the details for user 1 will be shown instead of the list of contacts.
Although you can’t see the navigation changes occurring in this demo, here’s the page in action:
Depending on which browser you’re using, if you hover over the links you should see the URL they’re pointing at.
If you want to see the page complete with navigation changes, you can view it here. As you interact with it notice how the URL changes between /contacts
and /contacts/1
.
What’s happening?
Blazor intercepts all attempts to navigate ‘within’ your app.
In practice this means, rather than dive off to a server to locate a page given a URL, Blazor will instead inspect the path you’re attempting to navigate to and determine which components need to be rendered.
In this case this one component is configured to handle two paths, with or without the contact id.
@page "/contacts/"
@page "/contacts/{id:int}"
When we click on a link which ends up at this same component, Blazor figures the component is already initialized and so rather than re-initialize it, re-renders it with the new parameters.
I’ve included some logging in the example for these lifecycle events:
- StateHasChanged
- OnAfterRender
- OnParametersSet
When we first hit this page, if we inspect the console (in the browser), we can see these events logged.
- Initialized
- OnParametersSet
- Rendered
After that though, when we navigate to the details for “Alice Krige” we see only these events logged:
- OnParametersSet
- Rendered
Notice that the component is not re-initialized.
This matters because, if you attempt to perform important work, like fetching data, in the OnInitialized
method, you’re going to be disappointed when you navigate around and find that data isn’t loading!
The answer? Move that work to the OnParametersSet
method instead.
protected override void OnParametersSet()
{
// need logic to run every time you navigate to this component? Put it here.
base.OnParametersSet();
}
Here you can fetch any data you like, confident that this method will always be invoked when navigation events bring the user to this component (whether they’re coming here from the “same” component, or a different one entirely).
Watch out for over eager data fetching
If you want to be a little more circumspect about when to perform actions in OnParameterSet
, you can implement your own check to see if a relevant parameter has changed.
For example, you might want to fetch contact details, but only if the Id
parameter has changed.
Here’s one way of implementing that check…
int? previousId;
protected override void OnParametersSet()
{
if (Id.HasValue && Id != previousId)
{
// fetch contact details
Console.WriteLine("Fetching contact details");
previousId = Id;
}
base.OnParametersSet();
}
Here we check if we have a value in previousId
and whether it matches the current value for our Id
parameter.
If the incoming Id
and previousId
values differ we can go ahead and fetch the contact details.
We also need to remember to update the value of previousId
so we can perform this same check again next time.
Web development should be fun.
Write code, hit F5, view it in the browser and bask in the glory of a job well done.
But you're not basking… Why aren't you basking?!
Cut through all the noise and build better, simpler Blazor web applications with Practical Blazor Components.
Build Better Blazor Web Apps, Faster