budtags/skills/inertia-react-development/SKILL.md
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.
npx skillsauth add jwilly246/budtags-claude-plugin inertia-react-developmentInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Activate this skill when:
<Form> or useForm)<Link> or routerUse search-docs for detailed Inertia v2 React patterns and documentation.
React page components should be placed in the resources/js/Pages directory.
export default function UsersIndex({ users }) { return ( <div> <h1>Users</h1> <ul> {users.map(user => <li key={user.id}>{user.name}</li>)} </ul> </div> ) }
</code-snippet>Use <Link> for client-side navigation instead of traditional <a> tags:
import { Link, router } from '@inertiajs/react'
<Link href="/">Home</Link> <Link href="/users">Users</Link> <Link href={`/users/${user.id}`}>View User</Link> </code-snippet>import { Link } from '@inertiajs/react'
<Link href="/logout" method="post" as="button"> Logout </Link> </code-snippet>Prefetch pages to improve perceived performance:
<code-snippet name="Prefetch on Hover" lang="react">import { Link } from '@inertiajs/react'
<Link href="/users" prefetch> Users </Link> </code-snippet>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!'), })
</code-snippet>The recommended way to build forms is with the <Form> component:
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>
)
}
</code-snippet>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>
</code-snippet>
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 successUse the search-docs tool with a query of form component resetting for detailed guidance.
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>
</code-snippet>
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 HookFor more programmatic control or to follow existing conventions, use the useForm hook:
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>
)
}
</code-snippet>Use deferred props to load data after initial page render:
<code-snippet name="Deferred Props with Empty State" lang="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> ) }
</code-snippet>Automatically refresh data at intervals:
<code-snippet name="Polling Example" lang="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>
)
}
</code-snippet>Load more data when user scrolls to a specific element:
<code-snippet name="Infinite Scroll with WhenVisible" lang="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>
)
}
</code-snippet><a> links instead of Inertia's <Link> component (breaks SPA behavior)undefined state of deferred props before data loads<form> without preventing default submission (use <Form> component or e.preventDefault())<Form> component is available in your Inertia versiondevelopment
Use this skill when generating ZPL code, working with ZPL commands, creating Zebra printer labels, or troubleshooting ZPL syntax and formatting issues.
development
Use this skill to verify that code aligns with BudTags coding standards, architectural patterns, and conventions before or after implementation.
development
Use this skill when working with Unleashed Software inventory/order management API integration, syncing inventory, importing orders, managing stock adjustments, or handling customer/product data from Unleashed.
data-ai
TanStack Virtual patterns for virtualized lists, tables, and grids with high-performance rendering of large datasets