Inertia.js v3 is a major release focused on simplicity and developer experience. It removes Axios, adds a Vite plugin that handles page resolution and SSR automatically, introduces standalone HTTP requests with useHttp, optimistic updates, instant visits and layout props. If you are starting a new Laravel + React project in 2026, v3 is the default. If you are upgrading from v2, this guide walks through the changes in the order you should apply them.
Key takeaway: The short version — v3 requires PHP 8.2+, Laravel 11+ and React 19+. Replace Axios with the built-in HTTP client, move page resolution to
@inertiajs/vite, republish the Inertia config, update the root Blade view and test SSR, forms and layouts. Most applications need a few hours, not a rewrite.
What is new in Inertia.js v3?
Vite plugin
In v2 every application repeated the same boilerplate: a resolve callback to map page names to components, a setup callback to mount the app, and a separate SSR entry point. The new @inertiajs/vite plugin handles all of it. Add the plugin to vite.config.js and call createInertiaApp() without arguments:
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import inertia from '@inertiajs/vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [
laravel({
input: ['resources/js/app.jsx'],
refresh: true,
}),
inertia({ pages: './Pages' }),
react(),
],
});
import { createInertiaApp } from '@inertiajs/react';
createInertiaApp();
The plugin resolves pages from ./Pages, handles lazy loading and code splitting, and wires up SSR. The setup and resolve callbacks are now optional — keep them only if you need custom behavior.
SSR in development without a separate server
In v2, SSR in development meant building the SSR bundle and starting a separate Node process. With the Vite plugin, SSR works automatically during development: run npm run dev and your pages are server-rendered. The production workflow is unchanged — build the client and SSR bundles and start the SSR server.
Axios removed
Inertia no longer ships with or depends on Axios. A built-in XHR client handles internal HTTP communication, which reduces the bundle and removes a dependency. The qs package is gone too. If you rely on Axios interceptors, migrate them to the built-in interceptors or keep Axios through the adapter.
useHttp for standalone requests
Not every request should trigger a page visit. Search endpoints, API calls and external services need plain HTTP without Inertia's page lifecycle. The useHttp hook gives you the same reactive state, error handling, upload progress and cancellation as useForm:
import { useHttp } from '@inertiajs/react';
const { data, setData, get, processing, errors } = useHttp({
query: '',
});
function search() {
get('/api/search', {
onSuccess: (response) => console.log(response),
});
}
Optimistic updates
Chain optimistic() before a router visit to apply changes immediately and roll them back automatically if the server rejects them:
router.optimistic((props) => ({
likes: props.likes + 1,
})).post(`/posts/${post.id}/like`);
Optimistic updates work with router visits, the <Form> component, useForm and useHttp. Multiple in-flight updates are tracked independently.
Instant visits
Instant visits swap to the target component immediately while the server request runs in the background. The user sees the new page right away with shared props; page-specific data merges in when the response arrives.
Layout props
Persistent layouts survive navigation, but sharing dynamic data with them used to require event buses or provide/inject. useLayoutProps and setLayoutProps solve that:
const { title } = useLayoutProps();
setLayoutProps({ title: 'Orders' });
Named layouts, nested layouts and static props are supported. You can also set a default layout in createInertiaApp.
Exception handling
Errors such as 404s can occur outside the Inertia middleware, where shared data and the root view are not available. handleExceptionsUsing() lets you render a custom Inertia error page with shared props:
use Inertia\Inertia;
Inertia::handleExceptionsUsing(function ($e) {
return Inertia::render('Error', [
'status' => $e->getStatusCode(),
])->withSharedData();
});
Returning null falls back to Laravel's default exception rendering.
Smaller improvements
- Nested prop types:
Inertia::optional(),Inertia::defer()andInertia::merge()work inside nested arrays, with dot-notation partial reloads. - Event renames:
invalid→httpException,exception→networkError, plus per-visitonHttpExceptionandonNetworkError. - Default layout in
createInertiaApp. - TypeScript generics for the
<Form>component. - PHP enums in
Inertia::render(). preserveErrorsfor partial reloads.- ESM-only packages.
Requirements
| Dependency | v3 requirement |
|---|---|
| PHP | 8.2+ |
| Laravel | 11+ |
| React | 19+ |
| Svelte | 5+ |
| Node.js | 20+ recommended |
If you are on React 18, stay on Inertia v2 until you upgrade React. If you are on Laravel 10 or PHP 8.1, upgrade the platform first — v3 will not install.
Upgrade step by step
1. Upgrade dependencies
npm install @inertiajs/react@^3.0
npm install @inertiajs/vite@^3.0
composer require inertiajs/inertia-laravel:^3.0
If you use Vue or Svelte, install the matching adapter (@inertiajs/vue3@^3.0 or @inertiajs/svelte@^3.0).
2. Republish the config
The Laravel configuration file was restructured. Republish it and re-apply your customizations
php artisan vendor:publish --provider="Inertia\ServiceProvider" --force
php artisan view:clear
3. Update the root Blade view
The inertia attribute in the <head> is now data-inertia
<title data-inertia>{{ config('app.name') }}</title>
You can also use the new Blade components
<head>
@vite('resources/js/app.jsx')
<x-inertia::head>
<title>{{ config('app.name') }}</title>
</x-inertia::head>
</head>
<body>
<x-inertia::app />
</body>
4. Add the Vite plugin
Add @inertiajs/vite to vite.config.js and simplify resources/js/app.jsx
import inertia from '@inertiajs/vite';
export default defineConfig({
plugins: [
laravel({ input: ['resources/js/app.jsx'], refresh: true }),
inertia({ pages: './Pages' }),
react(),
],
});
import { createInertiaApp } from '@inertiajs/react';
createInertiaApp();
Keep the explicit resolve callback if your pages live outside resources/js/Pages or need custom resolution.
5. Replace Axios
Search for axios imports in your frontend
rg "axios" resources/js
Replace internal request interceptors with the built-in client
import { router } from '@inertiajs/react';
router.on('httpException', (event) => {
// handle 4xx/5xx
});
For standalone requests, use useHttp or fetch. If you must keep Axios, install the adapter and follow the docs.
6. Fix breaking changes
Inertia::lazy()is removed — useInertia::optional().router.cancel()is nowrouter.cancelAll().- The
futureconfiguration block is removed; all v2 future flags are always enabled. hideProgress()andrevealProgress()named exports are removed — use theprogressobject.- React arrow-function layouts must be wrapped in an array:
Page.layout = [Layout]. - Form processing state resets in
onFinish, not immediately on response. - The initial page data is always passed via
<script type="application/json">; the legacydata-pageattribute is gone. - The
clearHistoryandencryptHistoryproperties are only included when true.
7. Test the upgrade
Run the full suite and check the critical paths manually
php artisan test
npm run build
npm run build:ssr
Test:
- login, logout and registration;
- forms with validation errors and file uploads;
- navigation with
preserveScrollandpreserveState; - partial reloads and deferred props;
- SSR output (view source, not just the rendered DOM);
- the production build, not only the dev server.
Warning: The most common upgrade failure is a stale config file. If pages do not resolve or SSR does not start, republish
config/inertia.php, clear cached views and restart the SSR process before debugging anything else.
Should you upgrade now?
Upgrade if
- you are starting a new project;
- you are on Laravel 11+ and React 19+;
- you want the Vite plugin,
useHttpor optimistic updates; - you are already planning a frontend refresh.
Wait if
- you are on React 18 and cannot upgrade yet;
- you are on Laravel 10 or PHP 8.1;
- you are in the middle of a release freeze.
The upgrade is not urgent for a stable v2 application, but v3 is the long-term path. Plan it as a focused sprint, not a background task.
FAQ
Is Inertia.js v3 stable?
Yes. v3 is released and documented, with an official upgrade guide. Test SSR and forms after upgrading — those are the areas most likely to need attention.
Do I have to use the Vite plugin?
No. It removes boilerplate and simplifies SSR, but the explicit resolve and setup callbacks still work. Use the plugin unless you have a custom page resolution strategy.
Can I keep Axios?
Yes, through the Axios adapter. Most applications do not need it — the built-in client covers interceptors and file uploads.
Does v3 support React 18?
No. The React adapter requires React 19+. Upgrade React first, or stay on v2.
What happens to Inertia::lazy()?
It was removed. Replace it with Inertia::optional(), which provides the same behavior.
Is SSR required?
No, but it is recommended for public pages. v3 makes SSR easier in development and keeps the production workflow similar.
How long does the upgrade take?
A typical Laravel + React application takes a few hours to a day, including testing. Large applications with custom page resolution and heavy Axios usage take longer.
Sources
- Inertia.js v3 upgrade guide
- Inertia.js v3 documentation
- Inertia.js v3 announcement
- Laravel documentation
- React 19 documentation
Need help upgrading a production Inertia.js application? Check our Laravel development services or hire a Laravel developer.
Read more: Inertia.js with Laravel and React, Inertia.js SSR with Laravel, Inertia.js performance optimization and Inertia.js SEO guide.