PHP package version
2.0.21
Inertia adapter(s) affected (if any)
Backend stack
laravel 12.53.0
PHP 8.5
Describe the problem
When using Inertia::once() in shared data (via HandleInertiaRequests::share()), two related problems arise that make it impossible to refresh a "once" prop after state changes.
Context
Inertia::once() is useful for sharing data that only needs to be sent once — for example, the authenticated user after login:
// HandleInertiaRequests.php
public function share(Request $request): array
{
return [
...parent::share($request),
'auth' => Inertia::once(fn () => ...)),
];
}
This works perfectly on the initial page load. However, both problems below make it impossible to re-deliver this prop after state changes (e.g. login, logout, profile update).
Problem : No API to invalidate or re-trigger a "once" prop
There is currently no way to tell Inertia "this once prop needs to be sent again on the next response". Once it has been sent, it is gone — even if the underlying data has changed.
This is a significant limitation for shared props that represent mutable state. If a user logs in, logs out, or updates their profile, the once prop reflecting that state becomes stale with no built-in mechanism to refresh it.
There is no equivalent of:
Inertia::refresh('auth'); // This does not exist yet
The only current workaround is to drop once entirely and use a regular shared prop, which sends the data on every request — defeating the entire purpose of once.
Problem 2: "Once" props are silently lost after a redirect when the destination component differs
When a controller mutates state and returns a redirect, once props defined in share() are never delivered to the client — and since there is no invalidation API (see Problem 1), there is no way to force them to be re-sent on the next request either.
The only mechanism doesn't work in that case, because of the way\Inertia\Response::isPartial() is done:
// vendor/inertiajs/inertia-laravel/src/Response.php:762
public function isPartial(Request $request): bool
{
return $request->header(Header::PARTIAL_COMPONENT) === $this->component;
}
When the frontend makes a partial visit (e.g. with only: ['auth']) and the server responds with a redirect to a different component, isPartial() returns false on the follow-up request because X-Inertia-Partial-Component no longer matches the destination component. The full props are resolved — but once props have already been evaluated on the previous request and are not re-evaluated.
Concrete example: The Login form page makes a partial visit to authenticate, passing only: ['auth']. The server logs the user in and redirects to / (a Dashboard component). On the follow-up request, isPartial() returns false (correct — it's a different component), but the user once-prop is never included the request is not considered partial.
// LoginController.php
public function store(Request $request): RedirectResponse
{
// ... authenticate user ...
auth()->guard('web')->login($user);
$request->session()->regenerate();
return redirect()->intended('/'); // ← user once-prop never reaches the client
}
The frontend never receives the updated auth prop after login, leaving components that depend on it stale.
Expected behavior
- There should be an explicit API to invalidate/re-trigger a
once prop, so that after a state mutation a controller can signal that the prop must be re-sent on the next response:
Inertia::refresh('auth');
once props should survive redirect boundaries — if a once prop could not be delivered because the response was a redirect (or because the destination component differed from the requesting component), it should be included in the response to the redirect's destination.
Thanks!
Steps to reproduce
- Define a
once shared prop in HandleInertiaRequests::share():
'auth' => Inertia::once(fn () => str_rand()),
-
On a login page, make a partial visit using only: ['auth'] (e.g. via a <Link> component with :only="['auth']").
-
The server authenticates the user and returns a redirect to a different page (e.g. Dashboard).
-
Inertia follows the redirect and makes a full, non-partial request to the destination page.
Expected: auth is included in the response since it's a full request and the prop hasn't been delivered yet.
Actual: auth is absent — the once closure was already evaluated and is not re-evaluated on the follow-up request.
- Define the same
once shared prop.
- Log the user in via any standard (non-partial) request.
- Try to force
auth to be re-sent on the next response from a controller — there is no API to do so.
- The only workaround is removing
once, causing the prop to be sent on every request.
PHP package version
2.0.21
Inertia adapter(s) affected (if any)
Backend stack
laravel 12.53.0
PHP 8.5
Describe the problem
When using
Inertia::once()in shared data (viaHandleInertiaRequests::share()), two related problems arise that make it impossible to refresh a "once" prop after state changes.Context
Inertia::once()is useful for sharing data that only needs to be sent once — for example, the authenticated user after login:This works perfectly on the initial page load. However, both problems below make it impossible to re-deliver this prop after state changes (e.g. login, logout, profile update).
Problem : No API to invalidate or re-trigger a "once" prop
There is currently no way to tell Inertia "this
onceprop needs to be sent again on the next response". Once it has been sent, it is gone — even if the underlying data has changed.This is a significant limitation for shared props that represent mutable state. If a user logs in, logs out, or updates their profile, the
onceprop reflecting that state becomes stale with no built-in mechanism to refresh it.There is no equivalent of:
The only current workaround is to drop
onceentirely and use a regular shared prop, which sends the data on every request — defeating the entire purpose ofonce.Problem 2: "Once" props are silently lost after a redirect when the destination component differs
When a controller mutates state and returns a redirect,
onceprops defined inshare()are never delivered to the client — and since there is no invalidation API (see Problem 1), there is no way to force them to be re-sent on the next request either.The
onlymechanism doesn't work in that case, because of the way\Inertia\Response::isPartial()is done:When the frontend makes a partial visit (e.g. with
only: ['auth']) and the server responds with a redirect to a different component,isPartial()returnsfalseon the follow-up request becauseX-Inertia-Partial-Componentno longer matches the destination component. The full props are resolved — butonceprops have already been evaluated on the previous request and are not re-evaluated.Concrete example: The
Loginform page makes a partial visit to authenticate, passingonly: ['auth']. The server logs the user in and redirects to/(aDashboardcomponent). On the follow-up request,isPartial()returnsfalse(correct — it's a different component), but theuseronce-prop is never included the request is not consideredpartial.The frontend never receives the updated
authprop after login, leaving components that depend on it stale.Expected behavior
onceprop, so that after a state mutation a controller can signal that the prop must be re-sent on the next response:onceprops should survive redirect boundaries — if aonceprop could not be delivered because the response was a redirect (or because the destination component differed from the requesting component), it should be included in the response to the redirect's destination.Thanks!
Steps to reproduce
onceshared prop inHandleInertiaRequests::share():On a login page, make a partial visit using
only: ['auth'](e.g. via a<Link>component with:only="['auth']").The server authenticates the user and returns a redirect to a different page (e.g.
Dashboard).Inertia follows the redirect and makes a full, non-partial request to the destination page.
Expected:
authis included in the response since it's a full request and the prop hasn't been delivered yet.Actual:
authis absent — theonceclosure was already evaluated and is not re-evaluated on the follow-up request.onceshared prop.authto be re-sent on the next response from a controller — there is no API to do so.once, causing the prop to be sent on every request.