home / skills / openagentsinc / openagents / inertia-react-development
/apps/openagents.com/.agents/skills/inertia-react-development
This skill helps you build Inertia.js v2 React applications, enabling pages, forms, and navigation with deferred props, prefetching, and polling.
npx playbooks add skill openagentsinc/openagents --skill inertia-react-developmentReview the files below or copy the command above to add this skill to your agents.
---
name: 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:
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>` or `useForm`)
- Implementing client-side navigation with `<Link>` or `router`
- 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:
<!-- Inertia React Navigation -->
```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
### Form Component (Recommended)
The recommended way to build forms is with the `<Form>` component:
<!-- Form Component Example -->
```react
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 -->
```react
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 fails
- `resetOnSuccess` - Reset form data when the request succeeds
- `setDefaultsOnSuccess` - Update default values on success
Use the `search-docs` tool with a query of `form component resetting` for detailed guidance.
<!-- Form with Reset Props -->
```react
import { Form } from '@inertiajs/react'
<Form
action="/users"
method="post"
resetOnSuccess
setDefaultsOnSuccess
>
{({ 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 -->
```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
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 -->
```react
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 -->
```react
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` (default `true`) — set to `false` to start polling manually via the returned `start()` function
- `keepAlive` (default `false`) — set to `true` to 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 -->
```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 `undefined` state of deferred props before data loads
- Using `<form>` without preventing default submission (use `<Form>` component or `e.preventDefault()`)
- Forgetting to check if `<Form>` component is available in your Inertia versionThis skill develops Inertia.js v2 React client applications, focusing on pages, navigation, forms, and client-side patterns. It activates when you work with <Link>, <Form>, useForm, router visits, deferred props, prefetching, polling, or other Inertia React features. The guidance optimizes SPA behavior, performance patterns, and common pitfalls.
The skill inspects React page structure and recommends Inertia-specific primitives: <Link> for client navigation, <Form> or useForm for submissions, router.visit for programmatic navigation, and hooks like usePoll and useForm for polling and state. It also checks for v2 features such as deferred props, prefetch flags, WhenVisible infinite scroll, and form reset behaviors to suggest loading states and error handling.
When should I use <Form> versus useForm?
Use <Form> for simple declarative forms that need built-in processing and reset behavior. Use useForm when you need programmatic control over data, partial resets, or custom submit flows.
How do I handle deferred props in components?
Render a skeleton or fallback UI when the prop is undefined, then render the real data once it arrives. Always guard against undefined to avoid runtime errors.