Implement OnInit/OnInitAsync and use it in sample HTTP request

This commit is contained in:
Steve Sanderson 2018-02-23 12:47:02 +00:00
parent 891f2a14d0
commit 423ad85a04
2 changed files with 61 additions and 18 deletions

View File

@ -8,21 +8,8 @@
@functions { @functions {
private string responseText; private string responseText;
// TODO: Move to OnInitAsync protected override async Task OnInitAsync()
protected override void OnParametersSet()
{ {
Http.GetStringAsync("/").ContinueWith(task => responseText = await Http.GetStringAsync("http://example.com/");
{
try
{
responseText = task.Result;
}
catch (Exception ex)
{
Console.Error.WriteLine(ex.InnerException.Message);
Console.Error.WriteLine(ex.InnerException.StackTrace);
}
StateHasChanged();
});
} }
} }

View File

@ -12,6 +12,13 @@ namespace Microsoft.AspNetCore.Blazor.Components
// Many of these names are used in code generation. Keep these in sync with the code generation code // Many of these names are used in code generation. Keep these in sync with the code generation code
// See: src/Microsoft.AspNetCore.Blazor.Razor.Extensions/BlazorComponent.cs // See: src/Microsoft.AspNetCore.Blazor.Razor.Extensions/BlazorComponent.cs
// Most of the developer-facing component lifecycle concepts are encapsulated in this
// base class. The core Blazor rendering system doesn't know about them (it only knows
// about IComponent). This gives us flexibility to change the lifecycle concepts easily,
// or for developers to design their own lifecycles as different base classes.
// TODO: When the component lifecycle design stabilises, add proper unit tests for BlazorComponent.
/// <summary> /// <summary>
/// Optional base class for Blazor components. Alternatively, Blazor components may /// Optional base class for Blazor components. Alternatively, Blazor components may
/// implement <see cref="IComponent"/> directly. /// implement <see cref="IComponent"/> directly.
@ -22,6 +29,7 @@ namespace Microsoft.AspNetCore.Blazor.Components
private readonly RenderFragment _renderFragment; private readonly RenderFragment _renderFragment;
private RenderHandle _renderHandle; private RenderHandle _renderHandle;
private bool _hasCalledInit;
private bool _hasNeverRendered = true; private bool _hasNeverRendered = true;
private bool _hasPendingQueuedRender; private bool _hasPendingQueuedRender;
@ -42,6 +50,25 @@ namespace Microsoft.AspNetCore.Blazor.Components
_hasNeverRendered = false; _hasNeverRendered = false;
} }
/// <summary>
/// Method invoked when the component is ready to start, having received its
/// initial parameters from its parent in the render tree.
/// </summary>
protected virtual void OnInit()
{
}
/// <summary>
/// Method invoked when the component is ready to start, having received its
/// initial parameters from its parent in the render tree.
///
/// Override this method if you will perform an asynchronous operation and
/// want the component to refresh when that operation is completed.
/// </summary>
/// <returns>A <see cref="Task"/> representing any asynchronous operation, or <see langword="null"/>.</returns>
protected virtual Task OnInitAsync()
=> null;
/// <summary> /// <summary>
/// Method invoked when the component has received parameters from its parent in /// Method invoked when the component has received parameters from its parent in
/// the render tree, and the incoming values have been assigned to properties. /// the render tree, and the incoming values have been assigned to properties.
@ -92,13 +119,42 @@ namespace Microsoft.AspNetCore.Blazor.Components
{ {
parameters.AssignToProperties(this); parameters.AssignToProperties(this);
// TODO: If we know conclusively that the parameters have not changed since last if (!_hasCalledInit)
// time (because they are all primitives and equal to the existing property values) {
// then skip the following. Can put an "out bool" parameter on AssignToProperties. _hasCalledInit = true;
OnInit();
// If you override OnInitAsync and return a nonnull task, then by default
// we automatically re-render once that task completes.
OnInitAsync()?.ContinueWith(task =>
{
if (task.Exception == null)
{
StateHasChanged();
}
else
{
HandleException(task.Exception);
}
});
}
OnParametersSet(); OnParametersSet();
StateHasChanged(); StateHasChanged();
} }
private void HandleException(Exception ex)
{
if (ex is AggregateException && ex.InnerException != null)
{
ex = ex.InnerException; // It's more useful
}
// TODO: Need better global exception handling
Console.Error.WriteLine($"[{ex.GetType().FullName}] {ex.Message}\n{ex.StackTrace}");
}
void IHandleEvent.HandleEvent(UIEventHandler handler, UIEventArgs args) void IHandleEvent.HandleEvent(UIEventHandler handler, UIEventArgs args)
{ {
handler(args); handler(args);