SKILL.blade.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. ---
  2. name: inertia-react-development
  3. 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."
  4. license: MIT
  5. metadata:
  6. author: laravel
  7. ---
  8. @php
  9. /** @var \Laravel\Boost\Install\GuidelineAssist $assist */
  10. @endphp
  11. # Inertia React Development
  12. ## Documentation
  13. Use `search-docs` for detailed Inertia v2 React patterns and documentation.
  14. ## Basic Usage
  15. ### Page Components Location
  16. React page components should be placed in the `{{ $assist->inertia()->pagesDirectory() }}` directory.
  17. ### Page Component Structure
  18. @boostsnippet("Basic React Page Component", "react")
  19. export default function UsersIndex({ users }) {
  20. return (
  21. <div>
  22. <h1>Users</h1>
  23. <ul>
  24. {users.map(user => <li key={user.id}>{user.name}</li>)}
  25. </ul>
  26. </div>
  27. )
  28. }
  29. @endboostsnippet
  30. ## Client-Side Navigation
  31. ### Basic Link Component
  32. Use `<Link>` for client-side navigation instead of traditional `<a>` tags:
  33. @boostsnippet("Inertia React Navigation", "react")
  34. import { Link, router } from '@inertiajs/react'
  35. <Link href="/">Home</Link>
  36. <Link href="/users">Users</Link>
  37. <Link href={`/users/${user.id}`}>View User</Link>
  38. @endboostsnippet
  39. ### Link with Method
  40. @boostsnippet("Link with POST Method", "react")
  41. import { Link } from '@inertiajs/react'
  42. <Link href="/logout" method="post" as="button">
  43. Logout
  44. </Link>
  45. @endboostsnippet
  46. ### Prefetching
  47. Prefetch pages to improve perceived performance:
  48. @boostsnippet("Prefetch on Hover", "react")
  49. import { Link } from '@inertiajs/react'
  50. <Link href="/users" prefetch>
  51. Users
  52. </Link>
  53. @endboostsnippet
  54. ### Programmatic Navigation
  55. @boostsnippet("Router Visit", "react")
  56. import { router } from '@inertiajs/react'
  57. function handleClick() {
  58. router.visit('/users')
  59. }
  60. // Or with options
  61. router.visit('/users', {
  62. method: 'post',
  63. data: { name: 'John' },
  64. onSuccess: () => console.log('Success!'),
  65. })
  66. @endboostsnippet
  67. ## Form Handling
  68. @if($assist->inertia()->hasFormComponent())
  69. ### Form Component (Recommended)
  70. The recommended way to build forms is with the `<Form>` component:
  71. @boostsnippet("Form Component Example", "react")
  72. import { Form } from '@inertiajs/react'
  73. export default function CreateUser() {
  74. return (
  75. <Form action="/users" method="post">
  76. {({ errors, processing, wasSuccessful }) => (
  77. <>
  78. <input type="text" name="name" />
  79. {errors.name && <div>{errors.name}</div>}
  80. <input type="email" name="email" />
  81. {errors.email && <div>{errors.email}</div>}
  82. <button type="submit" disabled={processing}>
  83. {processing ? 'Creating...' : 'Create User'}
  84. </button>
  85. {wasSuccessful && <div>User created!</div>}
  86. </>
  87. )}
  88. </Form>
  89. )
  90. }
  91. @endboostsnippet
  92. ### Form Component With All Props
  93. @boostsnippet("Form Component Full Example", "react")
  94. import { Form } from '@inertiajs/react'
  95. <Form action="/users" method="post">
  96. {({
  97. errors,
  98. hasErrors,
  99. processing,
  100. progress,
  101. wasSuccessful,
  102. recentlySuccessful,
  103. clearErrors,
  104. resetAndClearErrors,
  105. defaults,
  106. isDirty,
  107. reset,
  108. submit
  109. }) => (
  110. <>
  111. <input type="text" name="name" defaultValue={defaults.name} />
  112. {errors.name && <div>{errors.name}</div>}
  113. <button type="submit" disabled={processing}>
  114. {processing ? 'Saving...' : 'Save'}
  115. </button>
  116. {progress && (
  117. <progress value={progress.percentage} max="100">
  118. {progress.percentage}%
  119. </progress>
  120. )}
  121. {wasSuccessful && <div>Saved!</div>}
  122. </>
  123. )}
  124. </Form>
  125. @endboostsnippet
  126. @if($assist->inertia()->hasFormComponentResets())
  127. ### Form Component Reset Props
  128. The `<Form>` component supports automatic resetting:
  129. - `resetOnError` - Reset form data when the request fails
  130. - `resetOnSuccess` - Reset form data when the request succeeds
  131. - `setDefaultsOnSuccess` - Update default values on success
  132. Use the `search-docs` tool with a query of `form component resetting` for detailed guidance.
  133. @boostsnippet("Form with Reset Props", "react")
  134. import { Form } from '@inertiajs/react'
  135. <Form
  136. action="/users"
  137. method="post"
  138. resetOnSuccess
  139. setDefaultsOnSuccess
  140. >
  141. {({ errors, processing, wasSuccessful }) => (
  142. <>
  143. <input type="text" name="name" />
  144. {errors.name && <div>{errors.name}</div>}
  145. <button type="submit" disabled={processing}>
  146. Submit
  147. </button>
  148. </>
  149. )}
  150. </Form>
  151. @endboostsnippet
  152. @else
  153. Note: This version of Inertia does not support `resetOnError`, `resetOnSuccess`, or `setDefaultsOnSuccess` on the `<Form>` component. Using these props will cause errors. Upgrade to Inertia v2.2.0+ to use these features.
  154. @endif
  155. 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.
  156. @endif
  157. ### `useForm` Hook
  158. @if($assist->inertia()->hasFormComponent() === false)
  159. For Inertia v2.0.x: Build forms using the `useForm` helper as the `<Form>` component is not available until v2.1.0+.
  160. @else
  161. For more programmatic control or to follow existing conventions, use the `useForm` hook:
  162. @endif
  163. @boostsnippet("useForm Hook Example", "react")
  164. import { useForm } from '@inertiajs/react'
  165. export default function CreateUser() {
  166. const { data, setData, post, processing, errors, reset } = useForm({
  167. name: '',
  168. email: '',
  169. password: '',
  170. })
  171. function submit(e) {
  172. e.preventDefault()
  173. post('/users', {
  174. onSuccess: () => reset('password'),
  175. })
  176. }
  177. return (
  178. <form onSubmit={submit}>
  179. <input
  180. type="text"
  181. value={data.name}
  182. onChange={e => setData('name', e.target.value)}
  183. />
  184. {errors.name && <div>{errors.name}</div>}
  185. <input
  186. type="email"
  187. value={data.email}
  188. onChange={e => setData('email', e.target.value)}
  189. />
  190. {errors.email && <div>{errors.email}</div>}
  191. <input
  192. type="password"
  193. value={data.password}
  194. onChange={e => setData('password', e.target.value)}
  195. />
  196. {errors.password && <div>{errors.password}</div>}
  197. <button type="submit" disabled={processing}>
  198. Create User
  199. </button>
  200. </form>
  201. )
  202. }
  203. @endboostsnippet
  204. ## Inertia v2 Features
  205. ### Deferred Props
  206. Use deferred props to load data after initial page render:
  207. @boostsnippet("Deferred Props with Empty State", "react")
  208. export default function UsersIndex({ users }) {
  209. // users will be undefined initially, then populated
  210. return (
  211. <div>
  212. <h1>Users</h1>
  213. {!users ? (
  214. <div className="animate-pulse">
  215. <div className="h-4 bg-gray-200 rounded w-3/4 mb-2"></div>
  216. <div className="h-4 bg-gray-200 rounded w-1/2"></div>
  217. </div>
  218. ) : (
  219. <ul>
  220. {users.map(user => (
  221. <li key={user.id}>{user.name}</li>
  222. ))}
  223. </ul>
  224. )}
  225. </div>
  226. )
  227. }
  228. @endboostsnippet
  229. ### Polling
  230. Use the `usePoll` hook to automatically refresh data at intervals. It handles cleanup on unmount and throttles polling when the tab is inactive.
  231. @boostsnippet("Basic Polling", "react")
  232. import { usePoll } from '@inertiajs/react'
  233. export default function Dashboard({ stats }) {
  234. usePoll(5000)
  235. return (
  236. <div>
  237. <h1>Dashboard</h1>
  238. <div>Active Users: {stats.activeUsers}</div>
  239. </div>
  240. )
  241. }
  242. @endboostsnippet
  243. @boostsnippet("Polling With Request Options and Manual Control", "react")
  244. import { usePoll } from '@inertiajs/react'
  245. export default function Dashboard({ stats }) {
  246. const { start, stop } = usePoll(5000, {
  247. only: ['stats'],
  248. onStart() {
  249. console.log('Polling request started')
  250. },
  251. onFinish() {
  252. console.log('Polling request finished')
  253. },
  254. }, {
  255. autoStart: false,
  256. keepAlive: true,
  257. })
  258. return (
  259. <div>
  260. <h1>Dashboard</h1>
  261. <div>Active Users: {stats.activeUsers}</div>
  262. <button onClick={start}>Start Polling</button>
  263. <button onClick={stop}>Stop Polling</button>
  264. </div>
  265. )
  266. }
  267. @endboostsnippet
  268. - `autoStart` (default `true`) — set to `false` to start polling manually via the returned `start()` function
  269. - `keepAlive` (default `false`) — set to `true` to prevent throttling when the browser tab is inactive
  270. ### WhenVisible (Infinite Scroll)
  271. Load more data when user scrolls to a specific element:
  272. @boostsnippet("Infinite Scroll with WhenVisible", "react")
  273. import { WhenVisible } from '@inertiajs/react'
  274. export default function UsersList({ users }) {
  275. return (
  276. <div>
  277. {users.data.map(user => (
  278. <div key={user.id}>{user.name}</div>
  279. ))}
  280. {users.next_page_url && (
  281. <WhenVisible
  282. data="users"
  283. params={{ page: users.current_page + 1 }}
  284. fallback={<div>Loading more...</div>}
  285. />
  286. )}
  287. </div>
  288. )
  289. }
  290. @endboostsnippet
  291. ## Common Pitfalls
  292. - Using traditional `<a>` links instead of Inertia's `<Link>` component (breaks SPA behavior)
  293. - Forgetting to add loading states (skeleton screens) when using deferred props
  294. - Not handling the `undefined` state of deferred props before data loads
  295. - Using `<form>` without preventing default submission (use `<Form>` component or `e.preventDefault()`)
  296. - Forgetting to check if `<Form>` component is available in your Inertia version