Skip to content

Commit 0b81d41

Browse files
committed
Added feature: Deferred props
1 parent 424d809 commit 0b81d41

File tree

8 files changed

+59
-11
lines changed

8 files changed

+59
-11
lines changed

InertiaNetCore/Inertia.cs

+3
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ public static class Inertia
3838

3939
public static LazyProp<T> Lazy<T>(Func<T?> callback) => _factory.Lazy(callback);
4040
public static LazyProp<T> Lazy<T>(Func<Task<T?>> callback) => _factory.Lazy(callback);
41+
42+
public static DeferredProp<T> Defer<T>(Func<T?> callback, string? group = null) => _factory.Defer(callback, group);
43+
public static DeferredProp<T> Defer<T>(Func<Task<T?>> callback, string? group = null) => _factory.Defer(callback, group);
4144

4245
public static AlwaysProp<T> Always<T>(Func<T?> callback) => _factory.Always(callback);
4346
public static AlwaysProp<T> Always<T>(Func<Task<T?>> callback) => _factory.Always(callback);

InertiaNetCore/Models/InertiaPage.cs

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
namespace InertiaNetCore.Models;
22

3-
public readonly record struct InertiaPage()
3+
public readonly record struct InertiaPage
44
{
5-
public InertiaProps Props { get; init; } = default!;
6-
public string Component { get; init; } = default!;
7-
public string? Version { get; init; } = null;
8-
public string Url { get; init; } = default!;
5+
public required InertiaProps Props { get; init; }
6+
public required Dictionary<string, List<string>> DeferredProps { get; init; }
7+
public required string Component { get; init; }
8+
public required string? Version { get; init; }
9+
public required string Url { get; init; }
910
}

InertiaNetCore/Models/InertiaProps.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ internal async Task<InertiaProps> ToProcessedProps(List<string>? partials)
1313

1414
foreach (var (key, value) in this)
1515
{
16-
if(partials is null && value is ILazyProp)
16+
if(partials is null && value is IIgnoreFirstProp)
1717
continue;
1818

1919
if(partials is not null && value is not IAlwaysProp && !partials.Contains(key, StringComparer.InvariantCultureIgnoreCase))

InertiaNetCore/Response.cs

+16
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System.Text.Json;
22
using InertiaNetCore.Extensions;
33
using InertiaNetCore.Models;
4+
using InertiaNetCore.Utils;
45
using Microsoft.AspNetCore.Http;
56
using Microsoft.AspNetCore.Mvc;
67
using Microsoft.AspNetCore.Mvc.ModelBinding;
@@ -21,6 +22,7 @@ public async Task ExecuteResultAsync(ActionContext context)
2122
Version = version,
2223
Url = context.HttpContext.RequestedUri(),
2324
Props = await GetFinalProps(context),
25+
DeferredProps = GetDeferredProps(context),
2426
};
2527

2628
if (!context.HttpContext.IsInertiaRequest())
@@ -70,6 +72,20 @@ private async Task<InertiaProps> GetFinalProps(ActionContext context)
7072
return finalProps;
7173
}
7274

75+
private Dictionary<string, List<string>> GetDeferredProps(ActionContext context)
76+
{
77+
if (context.IsInertiaPartialComponent(component))
78+
return [];
79+
80+
return props
81+
.Where(prop => prop.Value is IDeferredProp)
82+
.GroupBy(prop => (prop.Value as IDeferredProp)!.Group)
83+
.ToDictionary(
84+
g => g.Key ?? g.Select(x => x.Key).First(),
85+
g => g.Select(x => x.Key).ToList()
86+
);
87+
}
88+
7389
private static Dictionary<string, string> GetErrors(ActionContext context)
7490
{
7591
var sessionErrors = context.HttpContext.Session.GetString("errors");

InertiaNetCore/ResponseFactory.cs

+2
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ public void Flash(string key, string? value)
113113

114114
public LazyProp<T> Lazy<T>(Func<T?> callback) => new(callback);
115115
public LazyProp<T> Lazy<T>(Func<Task<T?>> callback) => new(callback);
116+
public DeferredProp<T> Defer<T>(Func<T?> callback, string? group) => new(callback, group);
117+
public DeferredProp<T> Defer<T>(Func<Task<T?>> callback, string? group) => new(callback, group);
116118
public AlwaysProp<T> Always<T>(Func<T?> callback) => new(callback);
117119
public AlwaysProp<T> Always<T>(Func<Task<T?>> callback) => new(callback);
118120
}

InertiaNetCore/Utils/DeferProp.cs

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
namespace InertiaNetCore.Utils;
2+
3+
/// <summary>
4+
/// Deferred props allow you to defer the loading of certain page data until after the initial page render.
5+
/// This can be useful for improving the perceived performance of your app by allowing the initial page render to happen as quickly as possible.
6+
/// </summary>
7+
public class DeferredProp<T> : InvokableProp<T>, IDeferredProp
8+
{
9+
public string? Group { get; }
10+
11+
public DeferredProp(Func<T?> callback, string? group) : base(callback)
12+
{
13+
Group = group;
14+
}
15+
16+
public DeferredProp(Func<Task<T?>> callbackAsync, string? group) : base(callbackAsync)
17+
{
18+
Group = group;
19+
}
20+
}

InertiaNetCore/Utils/Interfaces.cs

+10-4
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,24 @@
22

33
namespace InertiaNetCore.Utils;
44

5+
public interface IViteBuilder
6+
{
7+
HtmlString ReactRefresh();
8+
HtmlString Input(string path);
9+
}
10+
511
internal interface IInvokableProp
612
{
713
internal Task<object?> InvokeToObject();
814
}
915

1016
internal interface IAlwaysProp;
1117

12-
internal interface ILazyProp;
18+
internal interface IIgnoreFirstProp;
1319

20+
internal interface ILazyProp : IIgnoreFirstProp;
1421

15-
public interface IViteBuilder
22+
internal interface IDeferredProp : IIgnoreFirstProp
1623
{
17-
HtmlString ReactRefresh();
18-
HtmlString Input(string path);
24+
string? Group { get; }
1925
}

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,6 @@ export default defineConfig({
333333

334334
## Work in progress
335335

336-
- [ ] Deferred props
336+
- [x] Deferred props
337337
- [ ] Merging props
338338
- [ ] History encryption

0 commit comments

Comments
 (0)