Skip to content

Commit

Permalink
Allow prerendering components (#53)
Browse files Browse the repository at this point in the history
* allow prerendering using the PrerenderAttribute

* code format

* tests

* document PrerenderAttribute
  • Loading branch information
DavidVollmers authored Apr 12, 2024
1 parent faf98e0 commit 64b737c
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 5 deletions.
18 changes: 15 additions & 3 deletions docs/components/ComponentLifecycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,19 @@ public class MyComponent : IgnisComponentBase, IHandleAfterRender, IHandleEvent

## `ServerPrerendered` rendering mode

Also contrary to Razor components, Ignis component's lifecycle methods are not called twice when the rendering mode is
set to `ServerPrerendered`.
Contrary to Razor components, Ignis component's lifecycle methods are not called twice when the rendering mode is set
to `ServerPrerendered`.

If you still want to have the same behaviour as Razor components, you can implement the `IHandleAfterRender` interface.
If you still want to prerender your Ignis components, you can use the `PrerenderAttribute` to enable prerendering:

```csharp
@attribute [Prerender]
@inherits IgnisComponentBase

<div>
This content will be prerendered.
</div>
```

The prerender cycle will happen without calling the `OnInitialized` and `OnUpdate` methods. This can be useful if you
want to render loading states, placeholders or search engine relevant content.
15 changes: 13 additions & 2 deletions packages/Ignis.Components/IgnisComponentBase.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Components;
using System.Reflection;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;

namespace Ignis.Components;
Expand Down Expand Up @@ -37,7 +38,17 @@ public void Attach(RenderHandle renderHandle)

public async Task SetParametersAsync(ParameterView parameters)
{
if (HostContext.IsPrerendering) return;
if (HostContext.IsPrerendering)
{
var prerenderAttribute = GetType().GetCustomAttribute<PrerenderAttribute>();
if (prerenderAttribute == null) return;

parameters.SetParameterProperties(this);

UpdateCore(async: false);

return;
}

parameters.SetParameterProperties(this);

Expand Down
6 changes: 6 additions & 0 deletions packages/Ignis.Components/PrerenderAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Ignis.Components;

[AttributeUsage(AttributeTargets.Class)]
public sealed class PrerenderAttribute : Attribute
{
}
59 changes: 59 additions & 0 deletions tests/Ignis.Tests.Components/PrerenderComponentTests.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
@using Ignis.Components.Extensions
@using Microsoft.AspNetCore.Components.Rendering
@inherits TestContext

@code
{
[Fact]
public void Cycle()
{
Services.AddIgnis();

var context = new PrerenderHostContext();
Services.AddSingleton<IHostContext>(context);

context.IsPrerenderingValue = true;

var cut = RenderComponent<PrerenderComponent>();

var result = cut.Markup;
Assert.Equal("OnPrerender", result);

context.IsPrerenderingValue = false;

cut.Render();

result = cut.Markup;

Assert.Equal("OnInitialized", result);
}

[Prerender]
class PrerenderComponent : IgnisComponentBase
{
private string _message = "OnPrerender";

protected override void OnInitialized()
{
_message = "OnInitialized";
}

protected override void BuildRenderTree(RenderTreeBuilder builder)
{
builder.AddContent(0, _message);
}
}

class PrerenderHostContext : HostContextBase
{
public bool IsPrerenderingValue { get; set; }

public override bool IsPrerendering => IsPrerenderingValue;

public override bool IsServerSide => false;

public PrerenderHostContext() : base(Array.Empty<IComponentExtension>())
{
}
}
}

0 comments on commit 64b737c

Please sign in to comment.