|
| 1 | +--- |
| 2 | +title: Once Props |
| 3 | +--- |
| 4 | + |
| 5 | +Some data rarely changes, is expensive to compute, or is simply large. Rather than including this data in every response, you may use _once props_. These props are remembered by the client and reused on subsequent pages that include the same prop. This makes them ideal for [shared data](/v2/data-props/shared-data). |
| 6 | + |
| 7 | +## Creating Once Props |
| 8 | + |
| 9 | +To create a once prop, use the `Inertia::once()` method when returning your response. This method receives a callback that returns the prop data. |
| 10 | + |
| 11 | +```php |
| 12 | +return Inertia::render('Billing', [ |
| 13 | + 'plans' => Inertia::once(fn () => Plan::all()), |
| 14 | +]); |
| 15 | +``` |
| 16 | + |
| 17 | +After the client has received this prop, subsequent requests will skip resolving the callback and exclude the prop from the response. The client only remembers once props while navigating between pages that include them. |
| 18 | + |
| 19 | +Navigating to a page without the once prop will forget the remembered value, and it will be resolved again on the next page that has it. In practice, this is rarely an issue since once props are typically used as shared data or within a specific section of your application. |
| 20 | + |
| 21 | +## Forcing a Refresh |
| 22 | + |
| 23 | +You may force a once prop to be refreshed using the `fresh()` method. |
| 24 | + |
| 25 | +```php |
| 26 | +return Inertia::render('Billing', [ |
| 27 | + 'plans' => Inertia::once(fn () => Plan::all())->fresh(), |
| 28 | +]); |
| 29 | +``` |
| 30 | + |
| 31 | +This method also accepts a boolean, allowing you to conditionally refresh the prop. |
| 32 | + |
| 33 | +```php |
| 34 | +return Inertia::render('Billing', [ |
| 35 | + 'plans' => Inertia::once(fn () => Plan::all())->fresh($condition), |
| 36 | +]); |
| 37 | +``` |
| 38 | + |
| 39 | +## Refreshing from the Client |
| 40 | + |
| 41 | +You may refresh a once prop from the client-side using a [partial reload](/v2/data-props/partial-reloads). The server will always resolve a once prop when explicitly requested. |
| 42 | + |
| 43 | +<CodeGroup> |
| 44 | + |
| 45 | +```js Vue icon="vuejs" |
| 46 | +import { router } from '@inertiajs/vue3' |
| 47 | + |
| 48 | +router.reload({ only: ['plans'] }) |
| 49 | +``` |
| 50 | + |
| 51 | +```js React icon="react" |
| 52 | +import { router } from '@inertiajs/react' |
| 53 | + |
| 54 | +router.reload({ only: ['plans'] }) |
| 55 | +``` |
| 56 | + |
| 57 | +```js Svelte icon="s" |
| 58 | +import { router } from '@inertiajs/svelte' |
| 59 | + |
| 60 | +router.reload({ only: ['plans'] }) |
| 61 | +``` |
| 62 | + |
| 63 | +</CodeGroup> |
| 64 | + |
| 65 | +## Expiration |
| 66 | + |
| 67 | +You may set an expiration time using the `until()` method. This method accepts a `DateTimeInterface`, `DateInterval`, or an integer (seconds). The prop will be refreshed on a subsequent visit after the expiration time has passed. |
| 68 | + |
| 69 | +```php |
| 70 | +return Inertia::render('Dashboard', [ |
| 71 | + 'rates' => Inertia::once(fn () => ExchangeRate::all())->until(now()->addDay()), |
| 72 | +]); |
| 73 | +``` |
| 74 | + |
| 75 | +## Custom Keys |
| 76 | + |
| 77 | +You may assign a custom key to the prop using the `as()` method. This is useful when you want to share data across multiple pages while using different prop names. |
| 78 | + |
| 79 | +```php |
| 80 | +// Team member list... |
| 81 | +return Inertia::render('Team/Index', [ |
| 82 | + 'memberRoles' => Inertia::once(fn () => Role::all())->as('roles'), |
| 83 | +]); |
| 84 | + |
| 85 | +// Invite form... |
| 86 | +return Inertia::render('Team/Invite', [ |
| 87 | + 'availableRoles' => Inertia::once(fn () => Role::all())->as('roles'), |
| 88 | +]); |
| 89 | +``` |
| 90 | + |
| 91 | +Both pages share the same underlying data because they use the same custom key, so the prop is only resolved for whichever page you visit first. |
| 92 | + |
| 93 | +## Sharing Once Props |
| 94 | + |
| 95 | +You may share once props globally using the `Inertia::share()` method. |
| 96 | + |
| 97 | +```php |
| 98 | +Inertia::share('countries', Inertia::once(fn () => Country::all())); |
| 99 | +``` |
| 100 | + |
| 101 | +Or, for convenience, you may use the `shareOnce()` method. |
| 102 | + |
| 103 | +```php |
| 104 | +Inertia::shareOnce('countries', fn () => Country::all()); |
| 105 | +``` |
| 106 | + |
| 107 | +You may also chain `as()`, `fresh()`, and `until()` onto the `shareOnce` method. |
| 108 | + |
| 109 | +```php |
| 110 | +Inertia::shareOnce('countries', fn () => Country::all())->until(now()->addDay()); |
| 111 | +``` |
| 112 | + |
| 113 | +Additionally, you may define a dedicated `shareOnce()` method in your middleware. The middleware will evaluate both `share()` and `shareOnce()`, merging the results. |
| 114 | + |
| 115 | +```php |
| 116 | +class HandleInertiaRequests extends Middleware |
| 117 | +{ |
| 118 | + public function shareOnce(Request $request): array |
| 119 | + { |
| 120 | + return array_merge(parent::shareOnce($request), [ |
| 121 | + 'countries' => fn () => Country::all(), |
| 122 | + ]); |
| 123 | + } |
| 124 | +} |
| 125 | +``` |
| 126 | + |
| 127 | +## Prefetching |
| 128 | + |
| 129 | +Once props are compatible with [prefetching](/v2/data-props/prefetching). The client automatically includes any remembered once props in prefetched responses, so navigating to a prefetched page will already have the once props available. |
| 130 | + |
| 131 | +Prefetched pages containing an expired once prop will be invalidated from the cache. |
| 132 | + |
| 133 | +## Combining with Other Prop Types |
| 134 | + |
| 135 | +The `once()` modifier may be chained onto [deferred](/v2/data-props/deferred-props), [merge](/v2/data-props/merging-props), and [optional](/v2/data-props/partial-reloads#lazy-data-evaluation) props. |
| 136 | + |
| 137 | +```php |
| 138 | +return Inertia::render('Dashboard', [ |
| 139 | + 'permissions' => Inertia::defer(fn () => Permission::all())->once(), |
| 140 | + 'activity' => Inertia::merge(fn () => $user->recentActivity())->once(), |
| 141 | + 'categories' => Inertia::optional(fn () => Category::all())->once(), |
| 142 | +]); |
| 143 | +``` |
0 commit comments