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_vite.inertia import defer

@get("/users/{id}", component="Users/Show")
async def show_user(id: 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

lazy()

defer()

Loading

Manual (partial reload)

Automatic (after mount)

Grouping

No

Yes

Use Case

On-demand data

Slow initial data

Caching

No

Optional via .once()

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