The Inertia.js team released v3.8.0 with a WhenMounted component for rendering browser-only code under server-side rendering, opt-in support for integers beyond JavaScript's safe range as native BigInt values, and more:
WhenMounted for Browser-Only Components
Evan Burrell contributed a WhenMounted component for the React, Vue, and Svelte adapters. A component that reads window or document while rendering crashes server-side rendering with a "window is not defined" error.
The WhenMounted component renders its fallback on the server and its children once the component has mounted in the browser:
import { WhenMounted } from '@inertiajs/vue3'
<template> <WhenMounted> <SalesChart /> <template #fallback> <p>Loading chart...</p> </template> </WhenMounted></template>
In React, pass the children as a function so the browser-only code does not run on the server, since JSX children are evaluated before the component renders:
import { WhenMounted } from '@inertiajs/react' <WhenMounted fallback={<p>Loading chart...</p>}> {() => <SalesChart width={window.innerWidth} />}</WhenMounted>
The fallback shows only during SSR and the first hydration render, so the browser's first render matches the server HTML and there is no hydration mismatch. A WhenMounted that mounts later, such as after a client-side visit, renders its children right away.
See #3218 for more details.
Big Integers as Native BigInt Values
Pascal Baljet added support for integers outside JavaScript's safe integer range. PHP sends a 64-bit integer, such as a Snowflake ID, as a JSON number, and the browser rounds it when parsing the page, so 900719925474099988 becomes 900719925474100000 with no error.
The feature is opt-in on the server and needs inertia-laravel v3.5.0. Turn it on for every response with the preserve_big_integers option in config/inertia.php (or the INERTIA_PRESERVE_BIG_INTEGERS environment variable), or for a single response:
return Inertia::render('Orders/Show', [ 'id' => $order->id,])->preserveBigIntegers();
The adapter encodes large integers as { "$bigint": "..." } markers, and the client turns them back into BigInt values. Integers inside the safe range stay regular numbers:
defineProps({ id: BigInt })
<template> <p>Order {{ id }}</p> <!-- Order 900719925474099988 --></template>
This works for the initial page, visits, partial reloads, encrypted history, and SSR. A BigInt sent back through the router, a form, or Precognition is submitted as a string of digits, which Laravel's integer validation rule and $request->integer() accept.
See #3237 for more details.
Form Forwards Error and Flash Callbacks
Dale Weaver fixed the <Form> component so it passes onHttpException, onNetworkError, onBeforeUpdate, and onFlash to the visit. These callbacks were already part of the component's props, but the adapters never forwarded them, so an HTTP 500 or a network failure on a <Form> submission never called them. They now work the same as on useForm, and returning false from either error callback stops the global event and the default handling:
<Form action="/orders" method="post" @http-exception="(response) => { toast.error('Something went wrong'); return false }"> <!-- ... --></Form>
See #3262 for more details.
Out-of-Order Optimistic Responses
Pascal Baljet fixed a case where two optimistic updates were in flight and the first request's response arrived last. Its props were read before the second write, so applying them rolled the second update back on screen. The page then disagreed with the server until the next visit.
Optimistic requests now carry an ID, and a response is ignored when a later optimistic request has already succeeded. A failed request does not count, so an older successful response still updates the page after a newer request fails and rolls back.
See #3245 for more details.
History Restores After a Deploy
Lazizbek Ergashev fixed back and forward navigation across a deploy. When the browser reloaded the document on a back or forward navigation, Inertia restored the page from history state without checking its asset version. The new JavaScript bundle then rendered props from the previous deploy, and a prop added or renamed since then was undefined. Inertia now compares the versions and renders the freshly loaded page when they differ.
See #3264 for more details.
Release Notes
You can see the complete list of changes below and the diff between 3.7.1 and 3.8.0 on GitHub. The following release notes are directly from the GitHub release:
v3.8.0
- [3.x] Fix multi-byte UTF-8 corruption in SSR request body parsing by @onk in #3248
- Bump pnpm/action-setup from 6.0.10 to 6.1.0 in the github-actions group by @dependabot in #3261
- [3.x] Fix core types when Axios is not installed by @fouteox in #3258
- [3.x] Compare asset versions before restoring history on a back/forward reload by @lazerg in #3264
- [3.x] Prevent a stale optimistic response from reverting a newer optimistic update by @pascalbaljet in #3245
- [3.x] Prefer server.origin when resolving SSR CSS link URLs by @pascalbaljet in #3268
- [3.x] Avoid top-level await in the generated SSR bundle by @ramonmalcolm10 in #3239
- [3.x] Forward missing Form visit callbacks by @daleweaver777 in #3262
- [3.x] Add WhenMounted component by @evan-burrell in #3218
- [3.x] Improve tests in CI by @pascalbaljet in #3277
- [3.x] Bump dependencies by @pascalbaljet in #3278
- [3.x] Clean up in-flight cancelled prefetches by @gianpieropuleo in #3271
- [3.x] Handle already-aborted signals in the XHR client by @gianpieropuleo in #3273
- [3.x] Fix React InfiniteScroll scroll jump on Safari and CI flakiness by @pascalbaljet in #3282
- [3.x] Support big integers as native BigInt values by @pascalbaljet in #3237
- [3.x] Bump dependencies by @pascalbaljet in #3286
- [3.x] Silence
state_referenced_locallywarning in SvelteAppcomponent by @pascalbaljet in #3287