Skill v1.0.0
currentAutomated scan100/100name: inertia-react-development description: "Develops Inertia.js v2 React client-side applications. Activates when creating React pages, forms, or navigation; using <Link>, <Form>, useForm, or router; working with deferred props, prefetching, or polling; or when user mentions React with Inertia, React pages, React forms, or React navigation." license: MIT metadata: version: "1.0.0" author: laravel
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 -->
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:
<!-- Inertia React Navigation -->
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 -->
import { Link } from '@inertiajs/react'<Link href="/logout" method="post" as="button">Logout</Link>
Prefetching
Prefetch pages to improve perceived performance:
<!-- Prefetch on Hover -->
import { Link } from '@inertiajs/react'<Link href="/users" prefetch>Users</Link>
Programmatic Navigation
<!-- Router Visit -->
import { router } from '@inertiajs/react'function handleClick() {router.visit('/users')}// Or with optionsrouter.visit('/users', {method: 'post',data: { name: 'John' },onSuccess: () => console.log('Success!'),})
Form Handling
Form Component (Recommended)
The recommended way to build forms is with the <Form> component:
<!-- Form Component Example -->
import { Form } from '@inertiajs/react'export default function CreateUser() {return (<Form action="/users" method="post">{({ errors, processing, wasSuccessful }) => (<><input type="text" name="name" />{errors.name && <div>{errors.name}</div>}<input type="email" name="email" />{errors.email && <div>{errors.email}</div>}<button type="submit" disabled={processing}>{processing ? 'Creating...' : 'Create User'}</button>{wasSuccessful && <div>User created!</div>}</>)}</Form>)}
Form Component With All Props
<!-- Form Component Full Example -->
import { Form } from '@inertiajs/react'<Form action="/users" method="post">{({errors,hasErrors,processing,progress,wasSuccessful,recentlySuccessful,clearErrors,resetAndClearErrors,defaults,isDirty,reset,submit}) => (<><input type="text" name="name" defaultValue={defaults.name} />{errors.name && <div>{errors.name}</div>}<button type="submit" disabled={processing}>{processing ? 'Saving...' : 'Save'}</button>{progress && (<progress value={progress.percentage} max="100">{progress.percentage}%</progress>)}{wasSuccessful && <div>Saved!</div>}</>)}</Form>
Form Component Reset Props
The <Form> component supports automatic resetting:
resetOnError- Reset form data when the request failsresetOnSuccess- Reset form data when the request succeedssetDefaultsOnSuccess- Update default values on success
Use the search-docs tool with a query of form component resetting for detailed guidance.
<!-- Form with Reset Props -->
import { Form } from '@inertiajs/react'<Formaction="/users"method="post"resetOnSuccesssetDefaultsOnSuccess>{({ errors, processing, wasSuccessful }) => (<><input type="text" name="name" />{errors.name && <div>{errors.name}</div>}<button type="submit" disabled={processing}>Submit</button></>)}</Form>
Forms can also be built using the useForm helper for more programmatic control. Use the search-docs tool with a query of useForm helper for guidance.
useForm Hook
For more programmatic control or to follow existing conventions, use the useForm hook:
<!-- useForm Hook Example -->
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}><inputtype="text"value={data.name}onChange={e => setData('name', e.target.value)}/>{errors.name && <div>{errors.name}</div>}<inputtype="email"value={data.email}onChange={e => setData('email', e.target.value)}/>{errors.email && <div>{errors.email}</div>}<inputtype="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 -->
export default function UsersIndex({ users }) {// users will be undefined initially, then populatedreturn (<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
Use the usePoll hook to automatically refresh data at intervals. It handles cleanup on unmount and throttles polling when the tab is inactive.
<!-- Basic Polling -->
import { usePoll } from '@inertiajs/react'export default function Dashboard({ stats }) {usePoll(5000)return (<div><h1>Dashboard</h1><div>Active Users: {stats.activeUsers}</div></div>)}
<!-- Polling With Request Options and Manual Control -->
import { usePoll } from '@inertiajs/react'export default function Dashboard({ stats }) {const { start, stop } = usePoll(5000, {only: ['stats'],onStart() {console.log('Polling request started')},onFinish() {console.log('Polling request finished')},}, {autoStart: false,keepAlive: true,})return (<div><h1>Dashboard</h1><div>Active Users: {stats.activeUsers}</div><button onClick={start}>Start Polling</button><button onClick={stop}>Stop Polling</button></div>)}
autoStart(defaulttrue) — set tofalseto start polling manually via the returnedstart()functionkeepAlive(defaultfalse) — set totrueto prevent throttling when the browser tab is inactive
WhenVisible (Infinite Scroll)
Load more data when user scrolls to a specific element:
<!-- Infinite Scroll with WhenVisible -->
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 && (<WhenVisibledata="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