inertiajs
laravel new inerita
https://www.linkedin.com/learning/building-a-website-with-laravel-react-js-and-inertia/creating-an-inertia-navigation
laravel breesze
react with inertia
composer create-project --prefer-dist laravel/laravel my-inertia-app
for vue 3
composer require inertiajs/inertia-laravel
npm install @inertiajs/inertia @inertiajs/inertia-vue3
npm install @vitejs/plugin-vue
for react
composer require inertiajs/inertia-laravel
npm install @inertiajs/inertia @inertiajs/inertia-react
php artisan make:model Post -a
npm install
some starterr kits
composer require laravel/breeze
php artisan breeze:install
or php artisan breeze:install
reac twith inertia
dark mode
php unit testing
what is valet link
some will be installed at web.php
<?php
use App\Http\Controllers\ProfileController;
use Illuminate\Foundation\Application;
use Illuminate\Support\Facades\Route;
use Inertia\Inertia;
Route::get('/', function () {
return Inertia::render('Welcome', [
'canLogin' => Route::has('login'),
'canRegister' => Route::has('register'),
'laravelVersion' => Application::VERSION,
'phpVersion' => PHP_VERSION,
]);
});
Route::get('/dashboard', function () {
return Inertia::render('Dashboard');
})->middleware(['auth', 'verified'])->name('dashboard');
Route::middleware('auth')->group(function () {
Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit');
Route::patch('/profile', [ProfileController::class, 'update'])->name('profile.update');
Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy');
});
require __DIR__.'/auth.php';
=
AFTER THAT
Route::resource('posts', PostController::class);
now we craete web and home pages
in web.php
short hadn routes which dontened controller
Route::inertia('about','About')->name('about');
route::view
in app.jsx already created when install breeze
import './bootstrap';
import '../css/app.css';
import { createRoot } from 'react-dom/client';
import { createInertiaApp } from '@inertiajs/react';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
const appName = import.meta.env.VITE_APP_NAME || 'Laravel';
createInertiaApp({
title: (title) => `${title} - ${appName}`,
resolve: (name) => resolvePageComponent(`./Pages/${name}.jsx`, import.meta.glob('./Pages/**/*.jsx')),
setup({ el, App, props }) {
const root = createRoot(el);
root.render(<App {...props} />);
},
progress: {
color: '#4B5563',
},
});
resources/js/pages/About.jsx
copy below code
export default function About() {
return (
<div>
<h1>About Page</h1>
<p>Welcome to the about page!</p>
</div>
);
}
error like below when reach about
for that purpise we have to run npm run dev
web.php
Route::get('/', function () {
return Inertia::render('Home', [
'canLogin' => Route::has('login'),
'canRegister' => Route::has('register'),
'laravelVersion' => Application::VERSION,
'phpVersion' => PHP_VERSION,
]);
});
remove the unnecesary routes
Route::get('/', function () {
return Inertia::render('Home');
});
create home.jsx
resources/js/pages/About.jsx
\
http://127.0.0.1:8000/
Home Page
Welcome to the about page!
create a navigatgion file in components fo;der
navigation.jsx
resources/js/components/navigation.jsx
write code clike below
import { Link } from "@inertiajs/react";
export default function Navigation() {
return (
<nav className="pb-5 mb-5 border-b">
<ul className="flex justify-end space-x-5">
<li>
<Link href={route("about")}>About</Link>
</li>
</ul>
</nav>
);
}
we dont have authentication,
so u can use guestlayout by started kit
resources/js/layouts/guestlayout.jsx
npm install @inertiajs/react
import ApplicationLogo from '@/Components/ApplicationLogo';
import { Link } from '@inertiajs/react';
export default function Guest({ children }) {
return (
<div className="min-h-screen flex flex-col sm:justify-center items-center pt-6 sm:pt-0 bg-gray-100">
<div>
<Link href="/">
<ApplicationLogo className="w-20 h-20 fill-current text-gray-500" />
</Link>
</div>
<div className="w-full sm:max-w-md mt-6 px-6 py-4 bg-white shadow-md overflow-hidden sm:rounded-lg">
{children}
</div>
</div>
);
}
=
add navigation
import Navigation from "@/Components/Navigation"
export default function Guest({ children }) {
return (
<div className="w-3/5 mx-auto my-10">
<Navigation />
<div >
{children}
</div>
</div>
);
}
resources/views/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">
<title inertia>{{ config('app.name', 'Laravel') }}</title>
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.bunny.net">
<link href="https://fonts.bunny.net/css?family=figtree:400,500,600&display=swap" rel="stylesheet" />
<!-- Scripts -->
@routes
@viteReactRefresh
@vite(['resources/js/app.jsx', "resources/js/Pages/{$page['component']}.jsx"])
@inertiaHead
</head>
<body class="font-sans antialiased">
@inertia
</body>
</html>
resources/js/app.jsx
title: (title) => `${title} - ${appName}`,
change to below
createInertiaApp({
title: (title) => `inertia and react`,
app.jsx
title: (title) => `${title} - ${appName}`,
guestlayout.jsx
import Navigation from "@/Components/Navigation"; // Ensure the path is correct
import { Head } from '@inertiajs/react';
export default function Guest({ children }) {
return (
<>
<Head title="linkedin learning" />
<div className="w-3/5 mx-auto my-10">
<Navigation />
<div>
{children}
</div>
</div>
</>
);
}
=
title displayas linked-in learning -laravel
in app.blade.php
<title inertia>{{ config('app.name', 'Laravel') }}</title>
=
resoources/js/pages/home.jsx
import GuestLayout from '@/Layouts/GuestLayout';
export default function Home({ posts }) {
return (
<GuestLayout>
<div>
<h1>Home Page</h1>
<p>Welcome to the Home page!</p>
<Posts posts={posts} />
</div>
</GuestLayout>
);
}
=
posts/oindex.jsx
import { Link } from '@inertiajs/react'; // Ensure Link is correctly imported from @inertiajs/react
export default function Index() {
const posts = []; // Replace with your actual posts data
const handleDeletePost = (postId) => {
// Add your delete logic here
};
return (
<div>
<div className='flex'>
<Link to="/posts/create" className="px-4 py-2">
Create New Post
</Link>
</div>
{posts && posts.map((post) => (
<div key={post.id} className="p-5 my-5 border rounded-md shadow-sm text-left">
<h2 className="mb-5 font-bold">{post.title}</h2>
<p>{post.body}</p>
<Link
to={`posts/update/${post.id}`}
state={post}
className="px-4 py-2 text-white bg-purple-500 rounded-md hover:bg-purple-600"
>
Edit Post
</Link>
<button
onClick={() => handleDeletePost(post.id)}
className="px-4 py-2 text-white bg-gray-400 rounded-md hover:bg-gray-500"
>
Delete Post
</button>
</div>
))}
</div>
);
}
=
resources/js/pages/home.jsx
import GuestLayout from '@/Layouts/GuestLayout';
import Posts from '@/Pages/Posts/Index'; // Import the Index component as Posts
export default function Home({ posts }) {
return (
<GuestLayout>
<div>
<h1>Home Page</h1>
<p>Welcome to the Home page!</p>
<Posts posts={posts} /> {/* Pass the posts prop to the Posts component */}
</div>
</GuestLayout>
);
}
===
create.jsx copied from react
modifield import and
const {data, setData, post, processing, errors} = useForm({
author: "",
title: "",
body: "",
});
// processing => form submission process
// setdata=>update the form data
// errors => an y errors,
and
value={data.body}
onChange={(e) => setData("body",e.target.value)}
=
create submit button
<button
type="submit"
disabled={processing}
className="px-4 py-2 mt-4 ml-4 text-white bg-purple-500 rounded-md hover:bg-purple-600"
>
Create Post
</button>
=
cancel
<Link
href={route('home')}
className="inline-block px-4 py-2 mt-4 text-black border rounded-md hover:bg-gray-200"
>
Cancel
</Link>
postcopntrller
public function index()
{
return Inertia::render("Home",[
'posts'=>Post::orderByDesc('created_at')->get(),
]);
composer require inertiajs/inertia-laravel
Route::resource('posts', PostController::class);
=
pages/posts/index.jsx
changed route ,
import { Link } from '@inertiajs/react'; // Ensure Link is correctly imported from @inertiajs/react
import { useEffect } from 'react';
export default function Index({ posts }) {
const handleDeletePost = (postId) => {
// Add your delete logic here
};
useEffect(() => {
console.log('s',posts); // Log the data received by the component
}, [posts]);
return (
<div>
<div className='flex'>
<Link href={route("posts.create")} className="px-4 py-2">
Create New Post
</Link>
</div>
{posts && posts.map((post) => (
<div key={post.id} className="p-5 my-5 border rounded-md shadow-sm text-left">
<Link
href={route("posts.show", post.id)}
className="px-4 py-2 bg-purple-500 rounded-md hover:bg-purple-600"
>
<h2 className="mb-5 font-bold">{post.title}</h2>
</Link>
<p>{post.title}</p>
<Link
href={route("posts.edit", post.id)}
className="px-4 py-2 text-white bg-purple-500 rounded-md hover:bg-purple-600"
>
Edit Post
</Link>
<button
onClick={() => handleDeletePost(post.id)}
className="px-4 py-2 text-white bg-gray-400 rounded-md hover:bg-gray-500"
>
Delete Post
</button>
</div>
))}
</div>
);
}
==
directly calling route names
postcontroller
public function index()
{
return Inertia::render("Home",[
'posts'=>Post::orderByDesc('created_at')->get(),
]);
==
now we modified route
from below which has postcontroller index that only fetch
at home page working
Route::resource('posts', PostController::class)->except('index');
Route::get('/', [PostController::class,'index'])->name('home');
home.jsx
import GuestLayout from '@/Layouts/GuestLayout';
import Posts from '@/Pages/Posts/Index'; // Import the Index component as Posts
export default function Home({ posts }) {
console.log('Home component posts:', posts);
return (
<GuestLayout>
<div>
<h1>Home Page</h1>
<p>Welcome to the Home page!</p>
<Posts posts={posts} /> {/* Pass the posts prop to the Posts component */}
</div>
</GuestLayout>
);
}
=
now all posts showign at home
this api is inside and js files is inside , so no need of axios, we can send directly
NOW CAREATE FORM
public function create()
{
return Inertia::render('Posts/Create');
}
STORE
public function store(StorePostRequest $request)
{
$data = $request->validated();
$post=Post::create($data);
$data=Post::query();
return redirect()->route('home');
=
CREATE.JSX
import { Link, useForm } from '@inertiajs/react';
import GuestLayout from '@/Layouts/GuestLayout';
export default function Create() {
const {data, setData, post, processing, errors} = useForm({
author: "",
title: "",
body: "",
});
// processing => form submission process
// setdata=>update the form data
// errors => an y errors,
const handleSubmit = async (e) => {
e.preventDefault();
post(route("posts.store"));
};
return (
<GuestLayout>
<form onSubmit={handleSubmit}>
<div className="flex flex-col space-y-8 text-left">
<h1 className="mx-auto text-xl">Create a new post</h1>
<label>
Title
<input
type="text"
value={data.title}
onChange={(e) => setData("title",e.target.value)}
className="block w-full rounded-md border-0 p-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-purple-200 sm:text-sm sm:leading-6"
/>
</label>
<label>
Author
<input
type="text"
value={data.author}
onChange={(e) => setData("author",e.target.value)}
className="block w-full rounded-md border-0 p-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-purple-200 sm:text-sm sm:leading-6"
/>
</label>
<label>
Main content
<textarea
value={data.body}
onChange={(e) => setData("body",e.target.value)}
className="block w-full rounded-md border-0 p-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-purple-200 sm:text-sm sm:leading-6"
/>
</label>
</div>
<div className="flex">
<Link
href={route('home')}
className="inline-block px-4 py-2 mt-4 text-black border rounded-md hover:bg-gray-200"
>
Cancel
</Link>
<button
type="submit"
disabled={processing}
className="px-4 py-2 mt-4 ml-4 text-white bg-purple-500 rounded-md hover:bg-purple-600"
>
Create Post
</button>
</div>
</form>
</GuestLayout>
);
};
=
DISPLAYING SIGNLE POST
public function show(Post $post)
{
return Inertia::render('Posts/Show', [
'post' => $post
]);
}
=
show.jsx
import GuestLayout from '@/Layouts/GuestLayout';
import { Link} from '@inertiajs/react';
import { useEffect } from 'react';
export default function Show({post}) {
// useEffect(() => {
// console.log('s',post); // Log the data received by the component
// }, [post]);
return (
<GuestLayout>
<Link
href={route('home')}
className="inline-block px-4 py-2 mt-4 text-black border rounded-md hover:bg-gray-200"
>
Home
</Link>
<div>
<div className='flex flex-col space-y-10'>
<h1 className="mx-auto">{post.title}</h1>
</div>
</div>
</GuestLayout>
);
}
=
update post
public function edit(Post $post)
{
return Inertia::render('Posts/Edit', [
'post' => $post
]);
=
public function update(UpdatePostRequest $request, Post $post)
{
$post->update($request->validated());
return redirect()->route('home');
=
import { Link, useForm } from '@inertiajs/react';
import GuestLayout from '@/Layouts/GuestLayout';
export default function Edit({post}) {
const {data, setData, put, processing, errors} = useForm({
title: post.title || "",
});
// processing => form submission process
// setdata=>update the form data
// errors => an y errors,
const handleSubmit = async (e) => {
e.preventDefault();
put(route("posts.update",post.id));
};
return (
<GuestLayout>
<form onSubmit={handleSubmit}>
<div className="flex flex-col space-y-8 text-left">
<h1 className="mx-auto text-xl">Create a new post</h1>
<label>
Title
<input
type="text"
value={data.title}
onChange={(e) => setData("title",e.target.value)}
className="block w-full rounded-md border-0 p-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-purple-200 sm:text-sm sm:leading-6"
/>
</label>
</div>
<div className="flex">
<Link
href={route('home')}
className="inline-block px-4 py-2 mt-4 text-black border rounded-md hover:bg-gray-200"
>
Cancel
</Link>
<button
type="submit"
disabled={processing}
className="px-4 py-2 mt-4 ml-4 text-white bg-purple-500 rounded-md hover:bg-purple-600"
>
update
</button>
</div>
</form>
</GuestLayout>
);
};
=
delete post
ublic function destroy(Post $post)
{
$post->delete();
return redirect()->route('home');
=
import { Link,router } from '@inertiajs/react'; // Ensure Link is correctly imported from @inertiajs/react
=
function deletePost(id)
{
router.delete(route("posts.destroy",id));
}
=
<button
onClick={() => deletePost(post.id)}
className="px-4 py-2 text-white bg-gray-400 rounded-md hover:bg-gray-500"
>
Delete Post
</button>
=
flash message
inertia shared data
allow access to data on numeroouse pages, eg: user name
enable in handleinertiarequests middlware
displa on page using usepage().props
https://inertiajs.com/shared-data
handleinertiarequest.php
write flash in share funciton
public function share(Request $request): array
{
return [
...parent::share($request),
'auth' => [
'user' => $request->user(),
],
'flash'=>[
'message' => fn() => $request->session()->get('message')
],
];
}
=
then write
public function destroy(Post $post)
{
$post->delete();
return redirect()->route('home')->with('message','Post Deleted');
=
import usepage
import { Link,router, usePage} from '@inertiajs/react';
=
const {flash } = usePage().props;
console.log('s',usePage().props);
=
display on page this flassh message on page
{flash.message && (
<div className="p-5">{flash.message}</div>
)}
=
index.jsx
import { Link,router, usePage} from '@inertiajs/react'; // Ensure Link is correctly imported from @inertiajs/react
import { useEffect } from 'react';
export default function Index({ posts }) {
const {flash } = usePage().props;
console.log('s',usePage().props);
const handleDeletePost = (postId) => {
// Add your delete logic here
};
function deletePost(id)
{
router.delete(route("posts.destroy",id));
}
// useEffect(() => {
// console.log('s',posts); // Log the data received by the component
// }, [posts]);
return (
<div>
{flash.message && (
<div className="p-5">{flash.message}</div>
)}
=
testing (cypress, laravel dusk)
data validation (laravel precognition)
@larabellesphp, www.larabelles.com
@zuzana_kunckova
www.zuzana-k.com
=