Deferred Props
Inertia’s deferred props feature allows you to defer the loading of certain page data until after the initial page render. This can be useful for improving the perceived performance of your app by allowing the initial page render to happen as quickly as possible.
Server Side
To defer a prop, you can use the Inertia::defer() method when returning your response. This method receives a callback that returns the prop data. The callback will be executed in a separate request after the initial page render.
public IActionResult Index(){ return Inertia.Render("Users/Index", new { Users = _context.Users.ToList(), Roles = _context.Roles.ToList(), Permissions = Inertia.Defer(() => _context.Permissions.ToList()), });}Route::get('/users', function () { return Inertia::render('Users/Index', [ 'users' => User::all(), 'roles' => Role::all(), 'permissions' => Inertia::defer(fn () => Permission::all()), ]);});Grouping Requests
By default, all deferred props get fetched in one request after the initial page is rendered, but you can choose to fetch data in parallel by grouping props together.
public IActionResult Index(){ return Inertia.Render("Users/Index", new { Users = _context.Users.ToList(), Roles = _context.Roles.ToList(), Permissions = Inertia.Defer(() => _context.Permissions.ToList()), Teams = Inertia.Defer(() => _context.Teams.ToList(), group: "attributes"), Projects = Inertia.Defer(() => _context.Projects.ToList(), group: "attributes"), Tasks = Inertia.Defer(() => _context.Tasks.ToList(), group: "attributes"), });}Route::get('/users', function () { return Inertia::render('Users/Index', [ 'users' => User::all(), 'roles' => Role::all(), 'permissions' => Inertia::defer(fn () => Permission::all()), 'teams' => Inertia::defer(fn () => Team::all(), 'attributes'), 'projects' => Inertia::defer(fn () => Project::all(), 'attributes'), 'tasks' => Inertia::defer(fn () => Task::all(), 'attributes'), ]);});In the example above, the teams, projects, and tasks props will be fetched in one request, while the permissions prop will be fetched in a separate request in parallel. Group names are arbitrary strings and can be anything you choose.
Client Side
On the client side, Inertia provides the Deferred component to help you manage deferred props. This component will automatically wait for the specified deferred props to be available before rendering its children.
<script setup>import { Deferred } from '@inertiajs/vue3'</script>
<template> <Deferred data="permissions"> <template #fallback> <div>Loading...</div> </template>
<div v-for="permission in permissions"> <!-- ... --> </div> </Deferred></template>import { Deferred } from '@inertiajs/react'
export default () => ( <Deferred data="permissions" fallback={<div>Loading...</div>}> <PermissionsChildComponent /> </Deferred>)<script> import { Deferred } from '@inertiajs/svelte'
export let permissions</script>
<Deferred data="permissions"> <svelte:fragment slot="fallback"> <div>Loading...</div> </svelte:fragment>
{#each permissions as permission} <!-- ... --> {/each}</Deferred><script> import { Deferred } from '@inertiajs/svelte'
let { permissions } = $props()</script>
<Deferred data="permissions"> {#snippet fallback()} <div>Loading...</div> {/snippet}
{#each permissions as permission} <!-- ... --> {/each}</Deferred>Multiple Deferred Props
If you need to wait for multiple deferred props to become available, you can specify an array to the data prop.
<script setup>import { Deferred } from '@inertiajs/vue3'</script>
<template> <Deferred :data="['teams', 'users']"> <template #fallback> <div>Loading...</div> </template>
<!-- Props are now loaded --> </Deferred></template>import { Deferred } from '@inertiajs/react'
export default () => ( <Deferred data={['teams', 'users']} fallback={<div>Loading...</div>}> <ChildComponent /> </Deferred>)<script> import { Deferred } from '@inertiajs/svelte'
export let teams export let users</script>
<Deferred data={['teams', 'users']}> <svelte:fragment slot="fallback"> <div>Loading...</div> </svelte:fragment>
<!-- Props are now loaded --></Deferred><script> import { Deferred } from '@inertiajs/svelte'
let { teams, users } = $props()</script>
<Deferred data={['teams', 'users']}> {#snippet fallback()} <div>Loading...</div> {/snippet}
<!-- Props are now loaded --></Deferred>Combining with Once Props
You may chain the once() modifier onto a deferred prop to ensure the data is resolved only once and remembered by the client across subsequent navigations.
return Inertia.Render("Dashboard", new { // InertiaCore exposes Defer and Once as separate prop types; pick one. // Use Inertia.Defer for a post-render fetch: Stats = Inertia.Defer(() => Stats.Generate()), // ...or Inertia.Once to resolve exactly once and remember the value client-side: // Stats = Inertia.Once(() => Stats.Generate()),});return Inertia::render('Dashboard', [ 'stats' => Inertia::defer(fn () => Stats::generate())->once(),]);For more information on once props, see the once props documentation.