Skip to content

Commit e2cb19d

Browse files
chuck-watersChuck Waterskapi2289
authored
Add async lazy prop logic (kapi2289#13)
* add async logic to lazy prop * convert to interface so that async lazy props can be added * added support for async lazy props * revert gitignore * missed bin/ in gitignore * update test to match example in readme * update test to match example in readme * fix a merge issue that overwrote defer prop checking * overload signature to take sync or async callback method * update readme * reverted the order of the using statements. VS automatically alph ordered them, but there were no file changes * Reformat code --------- Co-authored-by: Chuck Waters <chuck.waters@reusser.com> Co-authored-by: Kacper Ziubryniewicz <kacper@ziubryniewicz.pl>
1 parent 27c7866 commit e2cb19d

File tree

4 files changed

+102
-4
lines changed

4 files changed

+102
-4
lines changed

InertiaCore/ResponseFactory.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ internal interface IResponseFactory
2222
public void Share(string key, object? value);
2323
public void Share(IDictionary<string, object?> data);
2424
public LazyProp Lazy(Func<object?> callback);
25+
public LazyProp Lazy(Func<Task<object?>> callback);
2526
}
2627

2728
internal class ResponseFactory : IResponseFactory
@@ -118,5 +119,6 @@ public void Share(IDictionary<string, object?> data)
118119
context.Features.Set(sharedData);
119120
}
120121

121-
public LazyProp Lazy(Func<object?> callback) => new(callback);
122+
public LazyProp Lazy(Func<object?> callback) => new LazyProp(callback);
123+
public LazyProp Lazy(Func<Task<object?>> callback) => new LazyProp(callback);
122124
}

InertiaCore/Utils/LazyProp.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ namespace InertiaCore.Utils;
22

33
public class LazyProp
44
{
5-
private readonly Func<object?> _callback;
5+
private readonly Func<Task<object?>> _callback;
66

7-
public LazyProp(Func<object?> callback) => _callback = callback;
7+
public LazyProp(Func<object?> callback) => _callback = async () => await Task.FromResult(callback());
8+
public LazyProp(Func<Task<object?>> callback) => _callback = callback;
89

9-
public object? Invoke() => _callback.Invoke();
10+
public object? Invoke() => Task.Run(() => _callback.Invoke()).GetAwaiter().GetResult();
1011
}

InertiaCoreTests/UnitTestLazyData.cs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,75 @@ public void TestLazyPartialData()
6565
{ "errors", new Dictionary<string, string>(0) }
6666
}));
6767
}
68+
69+
70+
[Test]
71+
[Description("Test if the lazy async data is fetched properly.")]
72+
public void TestLazyAsyncData()
73+
{
74+
var testFunction = new Func<Task<object?>>(async () =>
75+
{
76+
Assert.Fail();
77+
await Task.Delay(100);
78+
return "Lazy Async";
79+
});
80+
81+
var response = _factory.Render("Test/Page", new
82+
{
83+
Test = "Test",
84+
TestFunc = new Func<string>(() => "Func"),
85+
TestLazy = _factory.Lazy(testFunction)
86+
});
87+
88+
var context = PrepareContext();
89+
90+
response.SetContext(context);
91+
response.ProcessResponse();
92+
93+
var page = response.GetJson().Value as Page;
94+
95+
Assert.That(page?.Props, Is.EqualTo(new Dictionary<string, object?>
96+
{
97+
{ "test", "Test" },
98+
{ "testFunc", "Func" },
99+
{ "errors", new Dictionary<string, string>(0) }
100+
}));
101+
}
102+
103+
[Test]
104+
[Description("Test if the lazy async data is fetched properly with specified partial props.")]
105+
public void TestLazyAsyncPartialData()
106+
{
107+
var testFunction = new Func<Task<string>>(async () =>
108+
{
109+
await Task.Delay(100);
110+
return "Lazy Async";
111+
});
112+
113+
var response = _factory.Render("Test/Page", new
114+
{
115+
TestFunc = new Func<string>(() => "Func"),
116+
TestLazy = _factory.Lazy(async () => await testFunction())
117+
});
118+
119+
var headers = new HeaderDictionary
120+
{
121+
{ "X-Inertia-Partial-Data", "testFunc,testLazy" },
122+
{ "X-Inertia-Partial-Component", "Test/Page" }
123+
};
124+
125+
var context = PrepareContext(headers);
126+
127+
response.SetContext(context);
128+
response.ProcessResponse();
129+
130+
var page = response.GetJson().Value as Page;
131+
132+
Assert.That(page?.Props, Is.EqualTo(new Dictionary<string, object?>
133+
{
134+
{ "testFunc", "Func" },
135+
{ "testLazy", "Lazy Async" },
136+
{ "errors", new Dictionary<string, string>(0) }
137+
}));
138+
}
68139
}

README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ and its usage is more similar to the official adapters'.
3131
* [Backend](#backend)
3232
- [Features](#features)
3333
* [Shared data](#shared-data)
34+
* [Async Lazy Props](#async-lazy-props)
3435
* [Server-side rendering](#server-side-rendering)
3536
* [Vite helper](#vite-helper)
3637
- [Examples](#examples-1)
@@ -165,6 +166,28 @@ app.Use(async (context, next) =>
165166
});
166167
```
167168

169+
### Async Lazy Props
170+
171+
You can use async lazy props to load data asynchronously in your components. This is useful for loading data that is not needed for the initial render of the page.
172+
```csharp
173+
174+
// simply use the LazyProps the same way you normally would, except pass in an async function
175+
176+
public async Task<IActionResult> Index()
177+
{
178+
var posts = new LazyProp(async () => await _context.Posts.ToListAsync());
179+
180+
var data = new
181+
{
182+
Posts = posts,
183+
};
184+
185+
return Inertia.Render("Posts", data);
186+
}
187+
188+
189+
```
190+
168191
### Server-side rendering
169192

170193
If you want to enable SSR in your Inertia app, remember to add `Inertia.Head()` to your layout:
@@ -224,6 +247,7 @@ builder.Services.AddViteHelper(options =>
224247
});
225248
```
226249

250+
227251
#### Examples
228252
---
229253

0 commit comments

Comments
 (0)