--- name: inertia-react-development description: "Develops Inertia.js v3 React client-side applications. Activates when creating React pages, forms, or navigation; using ,
, useForm, useHttp, setLayoutProps, or router; working with deferred props, prefetching, optimistic updates, instant visits, or polling; or when user mentions React with Inertia, React pages, React forms, or React navigation." license: MIT metadata: author: laravel --- @php /** @var \Laravel\Boost\Install\GuidelineAssist $assist */ @endphp # Inertia React Development ## When to Apply Activate this skill when: - Creating or modifying React page components for Inertia - Working with forms in React (using ``, `useForm`, or `useHttp`) - Implementing client-side navigation with `` or `router` - Using v3 features: deferred props, prefetching, optimistic updates, instant visits, layout props, HTTP requests, WhenVisible, InfiniteScroll, once props, flash data, or polling - Building React-specific features with the Inertia protocol ## Documentation Use `search-docs` for detailed Inertia v3 React patterns and documentation. ## Basic Usage ### Page Components Location React page components should be placed in the `{{ $assist->inertia()->pagesDirectory() }}` directory. ### Page Component Structure @boostsnippet("Basic React Page Component", "react") export default function UsersIndex({ users }) { return (

Users

) } @endboostsnippet ## Client-Side Navigation ### Basic Link Component Use `` for client-side navigation instead of traditional `` tags: @boostsnippet("Inertia React Navigation", "react") import { Link, router } from '@inertiajs/react' Home Users View User @endboostsnippet ### Link with Method @boostsnippet("Link with POST Method", "react") import { Link } from '@inertiajs/react' Logout @endboostsnippet ### Prefetching Prefetch pages to improve perceived performance: @boostsnippet("Prefetch on Hover", "react") import { Link } from '@inertiajs/react' Users @endboostsnippet ### Programmatic Navigation @boostsnippet("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!'), }) @endboostsnippet ## Form Handling @if($assist->inertia()->hasFormComponent()) ### Form Component (Recommended) The recommended way to build forms is with the `` component: @boostsnippet("Form Component Example", "react") import { Form } from '@inertiajs/react' export default function CreateUser() { return ( {({ errors, processing, wasSuccessful }) => ( <> {errors.name &&
{errors.name}
} {errors.email &&
{errors.email}
} {wasSuccessful &&
User created!
} )} ) } @endboostsnippet ### Form Component With All Props @boostsnippet("Form Component Full Example", "react") import { Form } from '@inertiajs/react'
{({ errors, hasErrors, processing, progress, wasSuccessful, recentlySuccessful, clearErrors, resetAndClearErrors, defaults, isDirty, reset, submit }) => ( <> {errors.name &&
{errors.name}
} {progress && ( {progress.percentage}% )} {wasSuccessful &&
Saved!
} )}
@endboostsnippet @if($assist->inertia()->hasFormComponentResets()) ### Form Component Reset Props The `
` 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. @boostsnippet("Form with Reset Props", "react") import { Form } from '@inertiajs/react' {({ errors, processing, wasSuccessful }) => ( <> {errors.name &&
{errors.name}
} )}
@endboostsnippet @else Note: This version of Inertia does not support `resetOnError`, `resetOnSuccess`, or `setDefaultsOnSuccess` on the `
` component. Using these props will cause errors. Upgrade to Inertia v2.2.0+ to use these features. @endif 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. @endif ### `useForm` Hook @if($assist->inertia()->hasFormComponent() === false) For Inertia v2.0.x: Build forms using the `useForm` helper as the `` component is not available until v2.1.0+. @else For more programmatic control or to follow existing conventions, use the `useForm` hook: @endif @boostsnippet("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 ( setData('name', e.target.value)} /> {errors.name &&
{errors.name}
} setData('email', e.target.value)} /> {errors.email &&
{errors.email}
} setData('password', e.target.value)} /> {errors.password &&
{errors.password}
}
) } @endboostsnippet ## Inertia v3 Features ### HTTP Requests Use the `useHttp` hook for standalone HTTP requests that do not trigger Inertia page visits. It provides the same developer experience as `useForm`, but for plain JSON endpoints. @boostsnippet("useHttp Example", "react") import { useHttp } from '@inertiajs/react' export default function Search() { const { data, setData, get, processing } = useHttp({ query: '', }) function search(e) { setData('query', e.target.value) get('/api/search', { onSuccess: (response) => { console.log(response) }, }) } return ( <> {processing &&
Searching...
} ) } @endboostsnippet ### Optimistic Updates Apply data changes instantly before the server responds, with automatic rollback on failure: @boostsnippet("Optimistic Update with Router", "react") import { router } from '@inertiajs/react' function like(post) { router.optimistic((props) => ({ post: { ...props.post, likes: props.post.likes + 1, }, })).post(`/posts/${post.id}/like`) } @endboostsnippet Optimistic updates also work with `useForm` and the `
` component: @boostsnippet("Optimistic Update with Form Component", "react") import { Form } from '@inertiajs/react' ({ todos: [...props.todos, { id: Date.now(), name: data.name, done: false }], })} >
@endboostsnippet ### Instant Visits Navigate to a new page immediately without waiting for the server response. The target component renders right away with shared props, while page-specific props load in the background. @verbatim @boostsnippet("Instant Visit with Link", "react") import { Link } from '@inertiajs/react' Dashboard View Post @endboostsnippet @endverbatim ### Layout Props Share dynamic data between pages and persistent layouts: @boostsnippet("Layout Props in Layout", "react") export default function Layout({ title = 'My App', showSidebar = true, children }) { return ( <>
{title}
{showSidebar && }
{children}
) } @endboostsnippet @boostsnippet("Setting Layout Props from Page", "react") import { setLayoutProps } from '@inertiajs/react' export default function Dashboard() { setLayoutProps({ title: 'Dashboard', showSidebar: false, }) return

Dashboard

} @endboostsnippet ### Deferred Props Use deferred props to load data after initial page render: @boostsnippet("Deferred Props with Empty State", "react") export default function UsersIndex({ users }) { return (

Users

{!users ? (
) : (
    {users.map(user => (
  • {user.name}
  • ))}
)}
) } @endboostsnippet ### Polling Use the `usePoll` hook to automatically refresh data at intervals. It handles cleanup on unmount and throttles polling when the tab is inactive. @boostsnippet("Basic Polling", "react") import { usePoll } from '@inertiajs/react' export default function Dashboard({ stats }) { usePoll(5000) return (

Dashboard

Active Users: {stats.activeUsers}
) } @endboostsnippet @boostsnippet("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 (

Dashboard

Active Users: {stats.activeUsers}
) } @endboostsnippet - `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 Lazy-load a prop when an element scrolls into view. Useful for deferring expensive data that sits below the fold: @boostsnippet("WhenVisible Example", "react") import { WhenVisible } from '@inertiajs/react' export default function Dashboard({ stats }) { return (

Dashboard

Loading stats...
}> {({ fetching }) => (

Total Users: {stats.total_users}

Revenue: {stats.revenue}

{fetching && Refreshing...}
)} ) } @endboostsnippet ### InfiniteScroll Automatically load additional pages of paginated data as users scroll: @boostsnippet("InfiniteScroll Example", "react") import { InfiniteScroll } from '@inertiajs/react' export default function Users({ users }) { return ( {users.data.map(user => (
{user.name}
))}
) } @endboostsnippet The server must use `Inertia::scroll()` to configure the paginated data. Use the `search-docs` tool with a query of `infinite scroll` for detailed guidance on buffers, manual loading, reverse mode, and custom trigger elements. ## Server-Side Patterns Server-side patterns (Inertia::render, props, middleware) are covered in inertia-laravel guidelines. ## Common Pitfalls - Using traditional `
` links instead of Inertia's `` 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 `
` without preventing default submission (use `` component or `e.preventDefault()`) - Forgetting to check if `` component is available in your Inertia version - Using `router.cancel()` instead of `router.cancelAll()` (v3 breaking change) - Using `router.on('invalid', ...)` or `router.on('exception', ...)` instead of the renamed `httpException` and `networkError` events