Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Defer Prop #531

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/DeferProp.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace Inertia;

use Illuminate\Support\Facades\App;

class DeferProp extends LazyProp
{
}
1 change: 1 addition & 0 deletions src/Inertia.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
* @method static void version(\Closure|string|null $version)
* @method static string getVersion()
* @method static \Inertia\LazyProp lazy(callable $callback)
* @method static \Inertia\DeferProp defer(callable $callback)
* @method static \Inertia\Response render(string $component, array|\Illuminate\Contracts\Support\Arrayable $props = [])
* @method static \Symfony\Component\HttpFoundation\Response location(string|\Symfony\Component\HttpFoundation\RedirectResponse $url)
* @method static void macro(string $name, object|callable $macro)
Expand Down
15 changes: 12 additions & 3 deletions src/Response.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,18 @@ public function rootView(string $rootView): self
public function toResponse($request)
{
$only = array_filter(explode(',', $request->header('X-Inertia-Partial-Data', '')));
$isPartial = ($only && $request->header('X-Inertia-Partial-Component') === $this->component);

$props = ($only && $request->header('X-Inertia-Partial-Component') === $this->component)
$props = $isPartial
? Arr::only($this->props, $only)
: array_filter($this->props, static function ($prop) {
return ! ($prop instanceof LazyProp);
return ! ($prop instanceof LazyProp || $prop instanceof DeferProp);
});

$deferProps = $isPartial ? [] : array_filter($this->props, static function ($prop) {
return $prop instanceof DeferProp;
});

$props = $this->resolvePropertyInstances($props, $request);

$page = [
Expand All @@ -103,6 +108,10 @@ public function toResponse($request)
'version' => $this->version,
];

if (!empty($deferProps)) {
$page['deferProps'] = array_keys($deferProps);
}

if ($request->header('X-Inertia')) {
return new JsonResponse($page, 200, ['X-Inertia' => 'true']);
}
Expand All @@ -120,7 +129,7 @@ public function resolvePropertyInstances(array $props, Request $request, bool $u
$value = App::call($value);
}

if ($value instanceof LazyProp) {
if ($value instanceof LazyProp || $value instanceof DeferProp) {
$value = App::call($value);
}

Expand Down
5 changes: 5 additions & 0 deletions src/ResponseFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ public function lazy(callable $callback): LazyProp
return new LazyProp($callback);
}

public function defer(callable $callback): DeferProp
{
return new DeferProp($callback);
}

/**
* @param array|Arrayable $props
*/
Expand Down
27 changes: 27 additions & 0 deletions tests/DeferPropTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace Inertia\Tests;

use Illuminate\Http\Request;
use Inertia\DeferProp;

class DeferPropTest extends TestCase
{
public function test_can_invoke(): void
{
$deferProp = new DeferProp(function () {
return 'A deferred value';
});

$this->assertSame('A deferred value', $deferProp());
}

public function test_can_resolve_bindings_when_invoked(): void
{
$deferProp = new DeferProp(function (Request $request) {
return $request;
});

$this->assertInstanceOf(Request::class, $deferProp());
}
}
13 changes: 12 additions & 1 deletion tests/ResponseFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Http\Request as HttpRequest;
use Illuminate\Session\Middleware\StartSession;
use Inertia\DeferProp;
use Illuminate\Session\NullSessionHandler;
use Illuminate\Session\Store;

Expand Down Expand Up @@ -160,12 +161,22 @@ public function test_can_create_lazy_prop(): void
$this->assertInstanceOf(LazyProp::class, $lazyProp);
}

public function test_can_create_defer_prop(): void
{
$factory = new ResponseFactory();
$deferProp = $factory->defer(function () {
return 'A deferred value';
});

$this->assertInstanceOf(DeferProp::class, $deferProp);
}

public function test_will_accept_arrayabe_props()
{
Route::middleware([StartSession::class, ExampleMiddleware::class])->get('/', function () {
Inertia::share('foo', 'bar');

return Inertia::render('User/Edit', new class() implements Arrayable {
return Inertia::render('User/Edit', new class () implements Arrayable {
public function toArray()
{
return [
Expand Down
42 changes: 40 additions & 2 deletions tests/ResponseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Http\Resources\Json\ResourceCollection;
use Inertia\DeferProp;

class ResponseTest extends TestCase
{
Expand Down Expand Up @@ -97,7 +98,7 @@ public function test_lazy_resource_response(): void
$callable = static function () use ($users) {
$page = new LengthAwarePaginator($users->take(2), $users->count(), 2);

return new class($page, JsonResource::class) extends ResourceCollection {
return new class ($page, JsonResource::class) extends ResourceCollection {
};
};

Expand Down Expand Up @@ -151,7 +152,7 @@ public function test_nested_lazy_resource_response(): void

// nested array with ResourceCollection to resolve
return [
'users' => new class($page, JsonResource::class) extends ResourceCollection {},
'users' => new class ($page, JsonResource::class) extends ResourceCollection {},
];
};

Expand Down Expand Up @@ -272,6 +273,24 @@ public function test_lazy_props_are_not_included_by_default(): void
$this->assertFalse(property_exists($page->props, 'lazy'));
}

public function test_defer_props_are_not_included_by_default(): void
{
$request = Request::create('/users', 'GET');
$request->headers->add(['X-Inertia' => 'true']);

$deferProp = new DeferProp(function () {
return 'A defer value';
});

$response = new Response('Users', ['users' => [], 'defer' => $deferProp], 'app', '123');
$response = $response->toResponse($request);
$page = $response->getData();

$this->assertSame([], $page->props->users);
$this->assertSame(['defer'], $page->deferProps);
$this->assertFalse(property_exists($page->props, 'defer'));
}

public function test_lazy_props_are_included_in_partial_reload(): void
{
$request = Request::create('/users', 'GET');
Expand All @@ -291,6 +310,25 @@ public function test_lazy_props_are_included_in_partial_reload(): void
$this->assertSame('A lazy value', $page->props->lazy);
}

public function test_defer_props_are_included_in_partial_reload(): void
{
$request = Request::create('/users', 'GET');
$request->headers->add(['X-Inertia' => 'true']);
$request->headers->add(['X-Inertia-Partial-Component' => 'Users']);
$request->headers->add(['X-Inertia-Partial-Data' => 'defer']);

$deferProp = new DeferProp(function () {
return 'A deferred value';
});

$response = new Response('Users', ['users' => [], 'defer' => $deferProp], 'app', '123');
$response = $response->toResponse($request);
$page = $response->getData();

$this->assertFalse(property_exists($page->props, 'users'));
$this->assertSame('A deferred value', $page->props->defer);
}

public function test_top_level_dot_props_get_unpacked(): void
{
$props = [
Expand Down
Loading