-
Notifications
You must be signed in to change notification settings - Fork 283
Description
PHP package version
2.0.21
Inertia adapter(s) affected (if any)
- React
- Vue 3
- Svelte
- Not Applicable
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 yetThe 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
onceprop, so that after a state mutation a controller can signal that the prop must be re-sent on the next response:
Inertia::refresh('auth');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
- Define a
onceshared prop inHandleInertiaRequests::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
onceshared prop. - Log the user in via any standard (non-partial) request.
- Try to force
authto 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.