Inertia React Development
When to Apply
Activate this skill when:
- •Creating or modifying React page components for Inertia
- •Working with forms in React (using
<Form>oruseForm) - •Implementing client-side navigation with
<Link>orrouter - •Using v2 features: deferred props, prefetching, or polling
- •Building React-specific features with the Inertia protocol
Documentation
Use search-docs for detailed Inertia v2 React patterns and documentation.
Basic Usage
Page Components Location
React page components should be placed in the resources/js/pages directory.
Page Component Structure
<!-- Basic React Page Component -->react
export default function UsersIndex({ users }) {
return (
<div>
<h1>Users</h1>
<ul>
{users.map(user => <li key={user.id}>{user.name}</li>)}
</ul>
</div>
)
}
Client-Side Navigation
Basic Link Component
Use <Link> for client-side navigation instead of traditional <a> tags:
react
import { Link, router } from '@inertiajs/react'
<Link href="/">Home</Link>
<Link href="/users">Users</Link>
<Link href={`/users/${user.id}`}>View User</Link>
Link with Method
<!-- Link with POST Method -->react
import { Link } from '@inertiajs/react'
<Link href="/logout" method="post" as="button">
Logout
</Link>
Prefetching
Prefetch pages to improve perceived performance:
<!-- Prefetch on Hover -->react
import { Link } from '@inertiajs/react'
<Link href="/users" prefetch>
Users
</Link>
Programmatic Navigation
<!-- Router Visit -->react
import { router } from '@inertiajs/react'
function handleClick() {
router.visit('/users')
}
// Or with options
router.visit('/users', {
method: 'post',
data: { name: 'John' },
onSuccess: () => console.log('Success!'),
})
Form Handling
useForm Hook
For Inertia v2.0.x: Build forms using the useForm helper as the <Form> component is not available until v2.1.0+.
react
import { useForm } from '@inertiajs/react'
export default function CreateUser() {
const { data, setData, post, processing, errors, reset } = useForm({
name: '',
email: '',
password: '',
})
function submit(e) {
e.preventDefault()
post('/users', {
onSuccess: () => reset('password'),
})
}
return (
<form onSubmit={submit}>
<input
type="text"
value={data.name}
onChange={e => setData('name', e.target.value)}
/>
{errors.name && <div>{errors.name}</div>}
<input
type="email"
value={data.email}
onChange={e => setData('email', e.target.value)}
/>
{errors.email && <div>{errors.email}</div>}
<input
type="password"
value={data.password}
onChange={e => setData('password', e.target.value)}
/>
{errors.password && <div>{errors.password}</div>}
<button type="submit" disabled={processing}>
Create User
</button>
</form>
)
}
Inertia v2 Features
Deferred Props
Use deferred props to load data after initial page render:
<!-- Deferred Props with Empty State -->react
export default function UsersIndex({ users }) {
// users will be undefined initially, then populated
return (
<div>
<h1>Users</h1>
{!users ? (
<div className="animate-pulse">
<div className="h-4 bg-gray-200 rounded w-3/4 mb-2"></div>
<div className="h-4 bg-gray-200 rounded w-1/2"></div>
</div>
) : (
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
)}
</div>
)
}
Polling
Automatically refresh data at intervals:
<!-- Polling Example -->react
import { router } from '@inertiajs/react'
import { useEffect } from 'react'
export default function Dashboard({ stats }) {
useEffect(() => {
const interval = setInterval(() => {
router.reload({ only: ['stats'] })
}, 5000) // Poll every 5 seconds
return () => clearInterval(interval)
}, [])
return (
<div>
<h1>Dashboard</h1>
<div>Active Users: {stats.activeUsers}</div>
</div>
)
}
WhenVisible (Infinite Scroll)
Load more data when user scrolls to a specific element:
<!-- Infinite Scroll with WhenVisible -->react
import { WhenVisible } from '@inertiajs/react'
export default function UsersList({ users }) {
return (
<div>
{users.data.map(user => (
<div key={user.id}>{user.name}</div>
))}
{users.next_page_url && (
<WhenVisible
data="users"
params={{ page: users.current_page + 1 }}
fallback={<div>Loading more...</div>}
/>
)}
</div>
)
}
Common Pitfalls
- •Using traditional
<a>links instead of Inertia's<Link>component (breaks SPA behavior) - •Forgetting to add loading states (skeleton screens) when using deferred props
- •Not handling the
undefinedstate of deferred props before data loads - •Using
<form>without preventing default submission (use<Form>component ore.preventDefault()) - •Forgetting to check if
<Form>component is available in your Inertia version