Deferred Props#
Props that load automatically after the initial page render.
See also
Official Inertia.js docs: Deferred Props
What Are Deferred Props?#
Deferred props are excluded from the initial page load and automatically fetched by the client after the page renders. This improves perceived performance for slow-loading data.
The defer() Helper#
from typing import Any
from litestar import get
from litestar_vite.inertia import defer
@get("/dashboard", component="Dashboard")
async def dashboard() -> dict[str, Any]:
return {
"user": get_current_user(), # Immediate
"stats": defer("stats", get_dashboard_stats), # Deferred
"chart": defer("chart", get_chart_data), # Deferred
}
The client automatically requests deferred props after mounting.
Grouped Deferred Props#
Group related props to fetch them together:
from typing import Any
from litestar import get
from litestar.params import FromPath
from litestar_vite.inertia import defer
@get("/users/{id}", component="Users/Show")
async def show_user(id: FromPath[int]) -> dict[str, Any]:
return {
"user": get_user(id), # Immediate
# Analytics group - fetched together
"pageViews": defer("pageViews", get_page_views, group="analytics"),
"engagement": defer("engagement", get_engagement, group="analytics"),
# Activity group - fetched together
"comments": defer("comments", get_comments, group="activity"),
"likes": defer("likes", get_likes, group="activity"),
}
Props in the same group are fetched in a single request.
Async Callbacks#
defer() supports both sync and async callbacks:
# Sync callback
defer("count", lambda: User.count())
# Async callback
async def get_slow_data():
await asyncio.sleep(1)
return {"slow": "data"}
defer("slow", get_slow_data)
Deferred Once Props#
You can combine deferred loading with client-side caching:
from litestar_vite.inertia import defer
@get("/reports", component="Reports")
async def reports() -> dict[str, Any]:
return {
"summary": defer("summary", build_summary).once(),
}
The prop is fetched after the initial render, then cached for later visits.
Frontend Handling#
The Inertia client shows loading states for deferred props:
import { usePage, Deferred } from "@inertiajs/react";
export default function Dashboard() {
return (
<div>
{/* Immediate data */}
<h1>Welcome, {usePage().props.user.name}</h1>
{/* Deferred data with loading fallback */}
<Deferred data="stats" fallback={<Spinner />}>
<Stats />
</Deferred>
</div>
);
}
<script setup>
import { Deferred } from "@inertiajs/vue3";
</script>
<template>
<div>
<h1>Welcome, {{ $page.props.user.name }}</h1>
<Deferred data="stats">
<template #fallback><Spinner /></template>
<Stats />
</Deferred>
</div>
</template>
Defer vs Lazy#
Feature |
|
|
|---|---|---|
Loading |
Manual (partial reload) |
Automatic (after mount) |
Grouping |
No |
Yes |
Use Case |
On-demand data |
Slow initial data |
Caching |
No |
Optional via |
Protocol Response#
Deferred props are included in the deferredProps field:
{
"component": "Dashboard",
"props": {"user": {"name": "Alice"}},
"deferredProps": {
"default": ["stats"],
"analytics": ["pageViews", "engagement"]
}
}
Advanced: Helper Utilities#
For advanced use cases, litestar-vite provides helper utilities:
from litestar_vite.inertia import extract_deferred_props
# Extract deferred props metadata from props dict
props = {
"users": [...],
"teams": defer("teams", get_teams, group="attributes"),
"projects": defer("projects", get_projects, group="attributes"),
"permissions": defer("permissions", get_permissions), # default group
}
groups = extract_deferred_props(props)
# Result: {"default": ["permissions"], "attributes": ["teams", "projects"]}
This is used internally by InertiaResponse to build the page object
with the deferredProps field for the Inertia v2 protocol.
See Also#
Partial Reloads - Manual partial reloads with lazy()
Merging Props - Infinite scroll patterns
Once Props - Client-cached props