🎉

inertia.jsのInertia::lazyは既にdeprecatedという話

2025/01/01に公開

https://inertiajs.com/partial-reloads#lazy-data-evaluation

Inertia.jsのドキュメントは本当に追いついてないので注意が必要だ。

src/ResponseFactory.php

    /**
     * @deprecated Use `optional` instead.
     */
    public function lazy(callable $callback): LazyProp
    {
        return new LazyProp($callback);
    }

    public function optional(callable $callback): OptionalProp
    {
        return new OptionalProp($callback);
    }

このように@deprecatedがマークされておりoptionalを代わりに使えと書いてある。

https://codecourse.com/articles/deferred-props-in-inertia

ここにもちょっとだけ書いてはある。

commit logの調査

https://github.com/inertiajs/inertia-laravel.git

これは369faff0061b49031dfafdc9699d4d8a76f7e0b4でdiffがあるが一言コメント感が強くどういう理由でこうなったのかはちょっと不明。ただ

この感じだと新たに追加されたdeferと以前のlazyが紛らわしいので、optionalという名前にしたというだけの話かもしれないね。なので

return Inertia::render('Users/Index', [
    'users' => Inertia::lazy(fn () => User::all()),
]);

ではなく

return Inertia::render('Users/Index', [
    'users' => Inertia::optional(fn () => User::all()),
]);

とする必要がある。

diffを眺めてみた。

% git --no-pager show 369faff0061b49031dfafdc9699d4d8a76f7e0b4
commit 369faff0061b49031dfafdc9699d4d8a76f7e0b4
Author: Joe Tannenbaum <joe.tannenbaum@laravel.com>
Date:   Tue Jul 9 12:58:02 2024 -0400

    lazy -> optional

diff --git a/src/Inertia.php b/src/Inertia.php
index 9e56c4e..b054f93 100644
--- a/src/Inertia.php
+++ b/src/Inertia.php
@@ -11,6 +11,7 @@ use Illuminate\Support\Facades\Facade;
  * @method static void flushShared()
  * @method static void version(\Closure|string|null $version)
  * @method static string getVersion()
+ * @method static \Inertia\OptionalProp optional(callable $callback)
  * @method static \Inertia\LazyProp lazy(callable $callback)
  * @method static \Inertia\DeferProp defer(callable $callback, string $group = 'default')
  * @method static \Inertia\AlwaysProp always(mixed $value)
diff --git a/src/OptionalProp.php b/src/OptionalProp.php
new file mode 100644
index 0000000..f3539b3
--- /dev/null
+++ b/src/OptionalProp.php
@@ -0,0 +1,20 @@
+<?php
+
+namespace Inertia;
+
+use Illuminate\Support\Facades\App;
+
+class OptionalProp
+{
+    protected $callback;
+
+    public function __construct(callable $callback)
+    {
+        $this->callback = $callback;
+    }
+
+    public function __invoke()
+    {
+        return App::call($this->callback);
+    }
+}
diff --git a/src/Response.php b/src/Response.php
index b288b16..cf5d4fd 100644
--- a/src/Response.php
+++ b/src/Response.php
@@ -114,7 +114,7 @@ class Response implements Responsable

         if (! $isPartial) {
             $props = array_filter($this->props, static function ($prop) {
-                return ! ($prop instanceof LazyProp) && ! ($prop instanceof DeferProp);
+                return ! ($prop instanceof OptionalProp) && ! ($prop instanceof LazyProp) && ! ($prop instanceof DeferProp);
             });
         }

@@ -228,7 +228,7 @@ class Response implements Responsable
                 $value = App::call($value);
             }

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

diff --git a/src/ResponseFactory.php b/src/ResponseFactory.php
index a7f6348..420644d 100644
--- a/src/ResponseFactory.php
+++ b/src/ResponseFactory.php
@@ -82,11 +82,19 @@ class ResponseFactory
         return (string) $version;
     }

+    /**
+     * @deprecated Use `optional` instead.
+     */
     public function lazy(callable $callback): LazyProp
     {
         return new LazyProp($callback);
     }

+    public function optional(callable $callback): OptionalProp
+    {
+        return new OptionalProp($callback);
+    }
+
     public function defer(callable $callback, string $group = 'default'): DeferProp
     {
         return new DeferProp($callback, $group);
diff --git a/tests/OptionalPropTest.php b/tests/OptionalPropTest.php
new file mode 100644
index 0000000..932c803
--- /dev/null
+++ b/tests/OptionalPropTest.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace Inertia\Tests;
+
+use Illuminate\Http\Request;
+use Inertia\OptionalProp;
+
+class OptionalPropTest extends TestCase
+{
+    public function test_can_invoke(): void
+    {
+        $optionalProp = new OptionalProp(function () {
+            return 'A lazy value';
+        });
+
+        $this->assertSame('A lazy value', $optionalProp());
+    }
+
+    public function test_can_resolve_bindings_when_invoked(): void
+    {
+        $optionalProp = new OptionalProp(function (Request $request) {
+            return $request;
+        });
+
+        $this->assertInstanceOf(Request::class, $optionalProp());
+    }
+}
diff --git a/tests/ResponseFactoryTest.php b/tests/ResponseFactoryTest.php
index 50d2c78..52add83 100644
--- a/tests/ResponseFactoryTest.php
+++ b/tests/ResponseFactoryTest.php
@@ -12,8 +12,10 @@ use Illuminate\Session\Store;
 use Illuminate\Support\Facades\Request;
 use Illuminate\Support\Facades\Route;
 use Inertia\AlwaysProp;
+use Inertia\DeferProp;
 use Inertia\Inertia;
 use Inertia\LazyProp;
+use Inertia\OptionalProp;
 use Inertia\ResponseFactory;
 use Inertia\Tests\Stubs\ExampleMiddleware;

@@ -161,6 +163,26 @@ class ResponseFactoryTest extends TestCase
         $this->assertInstanceOf(LazyProp::class, $lazyProp);
     }

+    public function test_can_create_deferred_prop(): void
+    {
+        $factory = new ResponseFactory();
+        $deferredProp = $factory->defer(function () {
+            return 'A deferred value';
+        });
+
+        $this->assertInstanceOf(DeferProp::class, $deferredProp);
+    }
+
+    public function test_can_create_optional_prop(): void
+    {
+        $factory = new ResponseFactory();
+        $optionalProp = $factory->optional(function () {
+            return 'An optional value';
+        });
+
+        $this->assertInstanceOf(OptionalProp::class, $optionalProp);
+    }
+
     public function test_can_create_always_prop(): void
     {
         $factory = new ResponseFactory();

まあ今年一年でInertia.jsも大分整ってくるといいですね。普通に使うには大体いけるんですけどね。

あけましておめでとうございます。

Discussion