aspnetcore icon indicating copy to clipboard operation
aspnetcore copied to clipboard

Inconsistent component initialization with Blazor SectionOutlet/SectionContent and CascadingValue

Open matthetherington opened this issue 4 months ago • 0 comments

Is there an existing issue for this?

  • [x] I have searched the existing issues

Describe the bug

With a <SectionOutlet /> in a layout:

MainLayout.razor:

@using Microsoft.AspNetCore.Components.Sections
@inherits LayoutComponentBase

@Body

<SectionOutlet SectionName="test" @rendermode="@RenderMode.InteractiveServer" />

and a simple page with a counter that has a variable inside a razor code block, along with a CascadingValue:

Home.razor:

@{
    var foo = "bar";
}

<CascadingValue Value="@(1)">
    <button @onclick="@(() => Task.CompletedTask)">Click</button>
    @foo
</CascadingValue>

<SectionContent SectionName="test">
    <TestComponent OnClick="@(() => Task.CompletedTask)" />
</SectionContent>

TestComponent.razor:

<h3>Hello World</h3>

The component underneath the<SectionContent> is re-initialized every time the counter button is clicked. If I put a breakpoint inside TestComponent.OnInitialized, it is hit every time the counter is incremented.

After changing:

var foo = "bar";

to

const string foo = "bar";

the breakpoint is no longer hit for each increment of the counter, and the same instance of TestComponent is kept around.

Similarly, removing the CascadingValue means the breakpoint is no longer hit:

@{
    var foo = "bar";
}

<button @onclick="@(() => Task.CompletedTask)">Click</button>
@foo

<SectionContent SectionName="test">
    <TestComponent OnClick="@(() => Task.CompletedTask)" />
</SectionContent>

The SectionContent itself is not disposed, just the component underneath it.

Also, if I move the SectionContent and it's ChildContent into a component of their own, initialization/disposal is only performed once. Like:

@page "/"

@{
    var foo = "bar";
}

<CascadingValue Value="@(1)">
    <button @onclick="@(HandleClick)">Click</button>
    @foo
</CascadingValue>

<SectionContentInComponent OnClick="HandleClick" />
@using Microsoft.AspNetCore.Components.Sections
<SectionContent SectionName="test">
    <TestComponent OnClick="@OnClick" />
</SectionContent>

@code {
    [Parameter] public EventCallback OnClick { get; set; }
}

Expected Behavior

TestComponent is not destroyed and recreated on each render.

Steps To Reproduce

https://github.com/matthetherington/BlazorSectionOutletIssueRepro

Exceptions (if any)

No response

.NET Version

8.0.303

Anything else?

.NET SDK:
 Version:           8.0.303
 Commit:            29ab8e3268
 Workload version:  8.0.300-manifests.b18aae85
 MSBuild version:   17.10.4+10fbfbf2e

Runtime Environment:
 OS Name:     Mac OS X
 OS Version:  15.0
 OS Platform: Darwin
 RID:         osx-arm64
 Base Path:   /usr/local/share/dotnet/sdk/8.0.303/

.NET workloads installed:
There are no installed workloads to display.

Host:
  Version:      9.0.0-rc.1.24431.7
  Architecture: arm64
  Commit:       static

.NET SDKs installed:
  6.0.401 [/usr/local/share/dotnet/sdk]
  7.0.404 [/usr/local/share/dotnet/sdk]
  8.0.300 [/usr/local/share/dotnet/sdk]
  8.0.303 [/usr/local/share/dotnet/sdk]
  9.0.100-rc.1.24452.12 [/usr/local/share/dotnet/sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.App 6.0.8 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 6.0.9 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 7.0.0 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 7.0.5 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 7.0.9 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 7.0.10 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 7.0.14 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 8.0.5 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 8.0.7 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 9.0.0-rc.1.24452.1 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 6.0.8 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.9 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 7.0.0 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 7.0.5 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 7.0.9 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 7.0.10 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 7.0.14 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 8.0.5 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 8.0.7 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 9.0.0-rc.1.24431.7 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]

Other architectures found:
  x64   [/usr/local/share/dotnet/x64]

Environment variables:
  Not set

global.json file:
  /Users/matt/Code/BlazorSectionOutletIssueRepro/global.json

Learn more:
  https://aka.ms/dotnet/info

Download .NET:
  https://aka.ms/dotnet/download

matthetherington avatar Oct 09 '24 13:10 matthetherington