Now, let's talk about links in Inertia. What do I mean by links? Currently, we only have the list of posts. Let's create another static page: for example, "About us". We will create two links above the table to link between the pages, and you will see the benefit of Inertia in terms of the SPA functionality.
First, let's create a new React component and add some text.
There are no Artisan commands to create React components. You have to do that manually.
resources/js/Pages/About.jsx:
export default function About() { return ( <div> About us </div> );}
Because this page is static, we can define Route similar to how we would do if defining Route only for a view.
routes/web.php:
Route::view('/', 'dashboard')->name('dashboard'); Route::get('posts', [PostController::class, 'index']);Route::inertia('about', 'About')->name('about');
And now, when we visit the /about
page, we can see the text from About
Vue component.
Now, let's add the links.
resources/js/Pages/Posts/Index.jsx:
export default function PostsIndex({ posts }) { return ( <div> <div className="mb-4"> <a className="mr-2" href="/posts">Posts</a> <a href="/about">About</a> </div> <table className="min-w-full divide-y divide-gray-200 border"> // ... );};
But, after clicking on the About in the Network tab, we can see that the page was fully reloaded with all the assets, which isn't SPA.
Instead of using a
tag we must use the Link
from Inertia.
resources/js/Pages/Posts/Index.jsx:
import { Link } from '@inertiajs/react'; export default function PostsIndex({ posts }) { return ( <div> <div className="mb-4"> <a className="mr-2" href="/posts">Posts</a> <a href="/about">About</a> <Link className="mr-2" href="/posts">Posts</Link> <Link href="/about">About</Link> </div> <table className="min-w-full divide-y divide-gray-200 border"> // ... );};
For now, let's copy these links to the About page.
resources/js/Pages/About.jsx:
import { Link } from '@inertiajs/react'; export default function About() { return ( <div> <div className="mb-4"> <Link className="mr-2" href="/posts">Posts</Link> <Link href="/about">About</Link> </div> About us </div> );}
Now, after refreshing the page, all the assets are loaded, but only the Inertia component is reloaded after going between pages.
Pages are now loading as SPA.
Next, let's examine route naming. It is much more convenient to call routes by their names. First, let's add names to the routes.
routes/web.php:
Route::view('/', 'dashboard')->name('dashboard'); Route::get('posts', [PostController::class, 'index'])->name('posts.index');Route::inertia('about', 'About')->name('about');
Now, where we added links instead of hard-coding them, we should be able to call them the same way as in a Blade file. By default, it is impossible, but a package tighten/ziggy gives this ability. Let's install this package.
composer require tightenco/ziggy
Then we must add the @routes
Blade directive to the main layout (before your application's JavaScript).
resources/views/layouts/app.blade.php:
<!DOCTYPE html><html lang="{{ str_replace('_', '-', app()->getLocale()) }}"><head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" /> @routes @viteReactRefresh @vite(['resources/css/app.css', 'resources/js/app.jsx']) @inertiaHead</head><body> @inertia</body></html>
Now, we can use the route()
helper in the React components.
resources/js/Pages/Posts/Index.jsx:
// ...<div className="mb-4"> <Link className="mr-2" href="/posts">Posts</Link> {/* <Link href="/about">About</Link> <Link className="mr-2" href={route('posts.index')}>Posts</Link> {/* <Link href={route('about')}>About</Link></div> // ...
resources/js/Pages/About.jsx:
// ...<div className="mb-4"> <Link className="mr-2" href="/posts">Posts</Link> {/* <Link href="/about">About</Link> <Link className="mr-2" href={route('posts.index')}>Posts</Link> {/* <Link href={route('about')}>About</Link></div> // ...
After visiting Posts or the About page visually, there is no difference, and going through pages, the result is the same. Only now, we're referencing the routes by names, so if, in the future, the endpoint for the route changes, you won't need to go through every page and change the URL manually.