💭
【ソース有】inertia.jsのLoad When Visibleのデモ
的な
オフィシャルドキュメントのリンク
前準備
routes/web.php
Route::get('/load-when-visible', LoadWhenVisibleController::class)->name('load-when-visible');
app/Http/Controllers/LoadWhenVisibleController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;
class LoadWhenVisibleController extends Controller
{
public function __invoke(Request $request): Response
{
$text = fake()->realText(2000);
return Inertia::render('LoadWhenVisible', [
'text' => $text,
]);
}
}
resources/js/Pages/LoadWhenVisible.jsx
export default function LoadWhenVisible({ text }) {
return (
<div className="min-h-screen bg-gray-50">
<header className="bg-white shadow">
<div className="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
<h1 className="text-3xl font-bold text-gray-900">Load When Visible Demo</h1>
</div>
</header>
<main className="py-10">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 space-y-12">
{[...Array(3)].map((_, index) => (
<section
key={index}
className="p-6 bg-white rounded-lg shadow-md hover:shadow-lg transition-shadow"
>
<p className="text-gray-700 leading-relaxed">{text}</p>
</section>
))}
</div>
</main>
</div>
);
}
とすると
こんな風になる。このダミーテキストの山を下に送ると何か出るみたいなデモを作る。
ユーザーのリストを追加
ここでさらにメソッドを追加し
app/Http/Controllers/LoadWhenVisibleController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;
use App\Models\User;
use Illuminate\Database\Eloquent\Collection;
class LoadWhenVisibleController extends Controller
{
public function __invoke(Request $request): Response
{
$text = fake()->realText(2000);
return Inertia::render('LoadWhenVisible', [
'text' => $text,
'users' => $this->getUsers(),
]);
}
public function getUsers(): Collection
{
return User::all();
}
}
と、ユーザー情報を全部取るみたいなよくあるgetUsers()
的なデモを与えた
ここで初期のseedではユーザーが少ないので追加しておく
database/seeders/DatabaseSeeder.php
User::factory()->create([
'name' => 'Test User',
'email' => 'test@example.com',
]);
User::factory(100)->create();
そしたらview
resources/js/Pages/LoadWhenVisible.jsx
export default function LoadWhenVisible({ text, users }) {
return (
<div className="min-h-screen bg-gray-50">
<header className="bg-white shadow">
<div className="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
<h1 className="text-3xl font-bold text-gray-900">Load When Visible Demo</h1>
</div>
</header>
<main className="py-10">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 space-y-12">
{[...Array(3)].map((_, index) => (
<section
key={index}
className="p-6 bg-white rounded-lg shadow-md hover:shadow-lg transition-shadow"
>
<p className="text-gray-700 leading-relaxed">{text}</p>
</section>
))}
<section className="mt-8 p-6 bg-white rounded-lg shadow-md">
<h2 className="text-2xl font-semibold text-gray-800 mb-4">User List</h2>
<ul className="divide-y divide-gray-200">
{users.map((user) => (
<li key={user.id} className="py-4 flex items-center">
<div className="w-10 h-10 rounded-full bg-blue-500 flex-shrink-0 flex items-center justify-center text-white font-bold">
{user.name.charAt(0).toUpperCase()}
</div>
<div className="ml-4">
<p className="text-sm font-medium text-gray-900">{user.name}</p>
<p className="text-sm text-gray-500">ID: {user.id}</p>
</div>
</li>
))}
</ul>
</section>
</div>
</main>
</div>
);
}
とすると
となる
いよいよWhenVisibleを加えていく
--- a/resources/js/Pages/LoadWhenVisible.jsx
+++ b/resources/js/Pages/LoadWhenVisible.jsx
@@ -1,3 +1,5 @@
+import { WhenVisible } from '@inertiajs/react'
+
export default function LoadWhenVisible({ text, users }) {
return (
<div className="min-h-screen bg-gray-50">
とし、
<WhenVisible data={['users']} fallback={<div>Loading...</div>}>
<div>moge</div>
</WhenVisible>
を置く。とりあえずユーザーのリストではなくmogeってみる
この時ロードに時間がかかってるテイを演出するために
public function getUsers(): Collection
{
sleep(2);
return User::all();
}
sleep(2)
を書き加えとる。しかし、これを行うと当然のようにこの関数がコールされて、ページ全体がおっそくなるので
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;
use App\Models\User;
use Illuminate\Database\Eloquent\Collection;
class LoadWhenVisibleController extends Controller
{
public function __invoke(Request $request): Response
{
$text = fake()->realText(2000);
return Inertia::render('LoadWhenVisible', [
'text' => $text,
'users' => Inertia::optional(fn() => $this->getUsers()),
]);
}
public function getUsers(): Collection
{
sleep(5);
return User::all();
}
}
このようにInertia::optionalとする。
return Inertia::render('LoadWhenVisible', [
'text' => $text,
// 'users' => Inertia::optional(fn() => $this->getUsers()),
'users' => fn () => $this->getUsers(),
]);
でもok。では実行してみよう
このように2秒後にmogeになったら、あとはもう勝ったようなもんやな
仕上げ
せっかくのreactなのでreact-spinnerも使ったろ
import { WhenVisible } from '@inertiajs/react'
import { ClipLoader } from 'react-spinners';
export default function LoadWhenVisible({ text, users }) {
return (
<div className="min-h-screen bg-gray-50">
<header className="bg-white shadow">
<div className="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
<h1 className="text-3xl font-bold text-gray-900">Load When Visible Demo</h1>
</div>
</header>
<main className="py-10">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 space-y-12">
{[...Array(3)].map((_, index) => (
<section
key={index}
className="p-6 bg-white rounded-lg shadow-md hover:shadow-lg transition-shadow"
>
<p className="text-gray-700 leading-relaxed">{text}</p>
</section>
))}
<section className="mt-8 p-6 bg-white rounded-lg shadow-md">
<h2 className="text-2xl font-semibold text-gray-800 mb-4">User List</h2>
<WhenVisible
data={['users']}
fallback={
<div className="flex justify-center items-center py-6">
<ClipLoader size={35} color={"#2563eb"} />
</div>
}
>
<ul className="divide-y divide-gray-200">
{users && users.map((user) => (
<li key={user.id} className="py-4 flex items-center">
<div className="w-10 h-10 rounded-full bg-blue-500 flex-shrink-0 flex items-center justify-center text-white font-bold">
{user.name.charAt(0).toUpperCase()}
</div>
<div className="ml-4">
<p className="text-sm font-medium text-gray-900">{user.name}</p>
<p className="text-sm text-gray-500">ID: {user.id}</p>
</div>
</li>
))}
</ul>
</WhenVisible>
</section>
</div>
</main>
</div>
);
}
ソース
Discussion