Eu tenho este componente pai:
<CascadingValue Value="@Email" IsFixed="true">
<Header />
<div class="container-fluid">
@Body
</div>
</CascadingValue>
@code {
[Parameter]
public string Email { get; set; }
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await base.OnAfterRenderAsync(firstRender);
if (!firstRender)
return;
Email = await GetEmailFromLocalStorage();
}
}
E o componente de cabeçalho (simplificado) é:
<Details></Details>
E o componente de detalhes (neto do pai):
@code {
[CascadingParameter]
public string Email { get; set; }
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await base.OnAfterRenderAsync(firstRender);
if (!firstRender)
return;
var email = Email; //Testing
}
}
Em tempo de execução, o componente pai começa a renderizar, mas então o neto começa a renderizar e o parâmetro 'Email' é nulo.
Por que isso acontece e a prática acima não é uma prática recomendada para passar parâmetros para componentes filhos?
OnAfterRenderAsync
faz o que promete. É executado como um evento de interface do usuário após a renderização do componente. Portanto, qualquer alteração de estado que você fizer não será refletida no estado de exibição sem uma nova renderização.Não existe "boa prática": existem apenas práticas boas e ruins. Tudo depende do contexto.
Você faz isso:
e então
O que é uma prática muito ruim. Você não deve sobrescrever
Parameter
propriedades definidas dentro do componente. Consulte https://learn.microsoft.com/en-us/aspnet/core/blazor/components/overwriting-parameters?view=aspnetcore-9.0 para obter uma explicação detalhada do porquê.A implementação a seguir deve funcionar no caso de uso que você forneceu. Ela usa um
TaskCompletionSource
para fornecer uma tarefa gerenciada manualmente. É basicamente um exemplo do que Brian Parker sugere.Primeiro, use "Layout" para representar sua página pai. Observe que estamos colocando um
Task<string>
.E seu
Details
:Página de demonstração: