Skip to content

Commit 79008f9

Browse files
v2: Rebuilt UI with Inertia + React (#175)
v2: Rebuilt UI with Inertia + React
2 parents a4367a3 + 0f5077d commit 79008f9

File tree

640 files changed

+33499
-21552
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

640 files changed

+33499
-21552
lines changed
Lines changed: 369 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,369 @@
1+
---
2+
name: inertia-react-development
3+
description: >-
4+
Develops Inertia.js v2 React client-side applications. Activates when creating
5+
React pages, forms, or navigation; using <Link>, <Form>, useForm, or router;
6+
working with deferred props, prefetching, or polling; or when user mentions
7+
React with Inertia, React pages, React forms, or React navigation.
8+
---
9+
10+
# Inertia React Development
11+
12+
## When to Apply
13+
14+
Activate this skill when:
15+
16+
- Creating or modifying React page components for Inertia
17+
- Working with forms in React (using `<Form>` or `useForm`)
18+
- Implementing client-side navigation with `<Link>` or `router`
19+
- Using v2 features: deferred props, prefetching, or polling
20+
- Building React-specific features with the Inertia protocol
21+
22+
## Documentation
23+
24+
Use `search-docs` for detailed Inertia v2 React patterns and documentation.
25+
26+
## Basic Usage
27+
28+
### Page Components Location
29+
30+
React page components should be placed in the `resources/js/pages` directory.
31+
32+
### Page Component Structure
33+
34+
<code-snippet name="Basic React Page Component" lang="react">
35+
36+
export default function UsersIndex({ users }) {
37+
return (
38+
<div>
39+
<h1>Users</h1>
40+
<ul>
41+
{users.map(user => <li key={user.id}>{user.name}</li>)}
42+
</ul>
43+
</div>
44+
)
45+
}
46+
47+
</code-snippet>
48+
49+
## Client-Side Navigation
50+
51+
### Basic Link Component
52+
53+
Use `<Link>` for client-side navigation instead of traditional `<a>` tags:
54+
55+
<code-snippet name="Inertia React Navigation" lang="react">
56+
57+
import { Link, router } from '@inertiajs/react'
58+
59+
<Link href="/">Home</Link>
60+
<Link href="/users">Users</Link>
61+
<Link href={`/users/${user.id}`}>View User</Link>
62+
63+
</code-snippet>
64+
65+
### Link with Method
66+
67+
<code-snippet name="Link with POST Method" lang="react">
68+
69+
import { Link } from '@inertiajs/react'
70+
71+
<Link href="/logout" method="post" as="button">
72+
Logout
73+
</Link>
74+
75+
</code-snippet>
76+
77+
### Prefetching
78+
79+
Prefetch pages to improve perceived performance:
80+
81+
<code-snippet name="Prefetch on Hover" lang="react">
82+
83+
import { Link } from '@inertiajs/react'
84+
85+
<Link href="/users" prefetch>
86+
Users
87+
</Link>
88+
89+
</code-snippet>
90+
91+
### Programmatic Navigation
92+
93+
<code-snippet name="Router Visit" lang="react">
94+
95+
import { router } from '@inertiajs/react'
96+
97+
function handleClick() {
98+
router.visit('/users')
99+
}
100+
101+
// Or with options
102+
router.visit('/users', {
103+
method: 'post',
104+
data: { name: 'John' },
105+
onSuccess: () => console.log('Success!'),
106+
})
107+
108+
</code-snippet>
109+
110+
## Form Handling
111+
112+
### Form Component (Recommended)
113+
114+
The recommended way to build forms is with the `<Form>` component:
115+
116+
<code-snippet name="Form Component Example" lang="react">
117+
118+
import { Form } from '@inertiajs/react'
119+
120+
export default function CreateUser() {
121+
return (
122+
<Form action="/users" method="post">
123+
{({ errors, processing, wasSuccessful }) => (
124+
<>
125+
<input type="text" name="name" />
126+
{errors.name && <div>{errors.name}</div>}
127+
128+
<input type="email" name="email" />
129+
{errors.email && <div>{errors.email}</div>}
130+
131+
<button type="submit" disabled={processing}>
132+
{processing ? 'Creating...' : 'Create User'}
133+
</button>
134+
135+
{wasSuccessful && <div>User created!</div>}
136+
</>
137+
)}
138+
</Form>
139+
)
140+
}
141+
142+
</code-snippet>
143+
144+
### Form Component With All Props
145+
146+
<code-snippet name="Form Component Full Example" lang="react">
147+
148+
import { Form } from '@inertiajs/react'
149+
150+
<Form action="/users" method="post">
151+
{({
152+
errors,
153+
hasErrors,
154+
processing,
155+
progress,
156+
wasSuccessful,
157+
recentlySuccessful,
158+
clearErrors,
159+
resetAndClearErrors,
160+
defaults,
161+
isDirty,
162+
reset,
163+
submit
164+
}) => (
165+
<>
166+
<input type="text" name="name" defaultValue={defaults.name} />
167+
{errors.name && <div>{errors.name}</div>}
168+
169+
<button type="submit" disabled={processing}>
170+
{processing ? 'Saving...' : 'Save'}
171+
</button>
172+
173+
{progress && (
174+
<progress value={progress.percentage} max="100">
175+
{progress.percentage}%
176+
</progress>
177+
)}
178+
179+
{wasSuccessful && <div>Saved!</div>}
180+
</>
181+
)}
182+
</Form>
183+
184+
</code-snippet>
185+
186+
### Form Component Reset Props
187+
188+
The `<Form>` component supports automatic resetting:
189+
190+
- `resetOnError` - Reset form data when the request fails
191+
- `resetOnSuccess` - Reset form data when the request succeeds
192+
- `setDefaultsOnSuccess` - Update default values on success
193+
194+
Use the `search-docs` tool with a query of `form component resetting` for detailed guidance.
195+
196+
<code-snippet name="Form with Reset Props" lang="react">
197+
198+
import { Form } from '@inertiajs/react'
199+
200+
<Form
201+
action="/users"
202+
method="post"
203+
resetOnSuccess
204+
setDefaultsOnSuccess
205+
>
206+
{({ errors, processing, wasSuccessful }) => (
207+
<>
208+
<input type="text" name="name" />
209+
{errors.name && <div>{errors.name}</div>}
210+
211+
<button type="submit" disabled={processing}>
212+
Submit
213+
</button>
214+
</>
215+
)}
216+
</Form>
217+
218+
</code-snippet>
219+
220+
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.
221+
222+
### `useForm` Hook
223+
224+
For more programmatic control or to follow existing conventions, use the `useForm` hook:
225+
226+
<code-snippet name="useForm Hook Example" lang="react">
227+
228+
import { useForm } from '@inertiajs/react'
229+
230+
export default function CreateUser() {
231+
const { data, setData, post, processing, errors, reset } = useForm({
232+
name: '',
233+
email: '',
234+
password: '',
235+
})
236+
237+
function submit(e) {
238+
e.preventDefault()
239+
post('/users', {
240+
onSuccess: () => reset('password'),
241+
})
242+
}
243+
244+
return (
245+
<form onSubmit={submit}>
246+
<input
247+
type="text"
248+
value={data.name}
249+
onChange={e => setData('name', e.target.value)}
250+
/>
251+
{errors.name && <div>{errors.name}</div>}
252+
253+
<input
254+
type="email"
255+
value={data.email}
256+
onChange={e => setData('email', e.target.value)}
257+
/>
258+
{errors.email && <div>{errors.email}</div>}
259+
260+
<input
261+
type="password"
262+
value={data.password}
263+
onChange={e => setData('password', e.target.value)}
264+
/>
265+
{errors.password && <div>{errors.password}</div>}
266+
267+
<button type="submit" disabled={processing}>
268+
Create User
269+
</button>
270+
</form>
271+
)
272+
}
273+
274+
</code-snippet>
275+
276+
## Inertia v2 Features
277+
278+
### Deferred Props
279+
280+
Use deferred props to load data after initial page render:
281+
282+
<code-snippet name="Deferred Props with Empty State" lang="react">
283+
284+
export default function UsersIndex({ users }) {
285+
// users will be undefined initially, then populated
286+
return (
287+
<div>
288+
<h1>Users</h1>
289+
{!users ? (
290+
<div className="animate-pulse">
291+
<div className="h-4 bg-gray-200 rounded w-3/4 mb-2"></div>
292+
<div className="h-4 bg-gray-200 rounded w-1/2"></div>
293+
</div>
294+
) : (
295+
<ul>
296+
{users.map(user => (
297+
<li key={user.id}>{user.name}</li>
298+
))}
299+
</ul>
300+
)}
301+
</div>
302+
)
303+
}
304+
305+
</code-snippet>
306+
307+
### Polling
308+
309+
Automatically refresh data at intervals:
310+
311+
<code-snippet name="Polling Example" lang="react">
312+
313+
import { router } from '@inertiajs/react'
314+
import { useEffect } from 'react'
315+
316+
export default function Dashboard({ stats }) {
317+
useEffect(() => {
318+
const interval = setInterval(() => {
319+
router.reload({ only: ['stats'] })
320+
}, 5000) // Poll every 5 seconds
321+
322+
return () => clearInterval(interval)
323+
}, [])
324+
325+
return (
326+
<div>
327+
<h1>Dashboard</h1>
328+
<div>Active Users: {stats.activeUsers}</div>
329+
</div>
330+
)
331+
}
332+
333+
</code-snippet>
334+
335+
### WhenVisible (Infinite Scroll)
336+
337+
Load more data when user scrolls to a specific element:
338+
339+
<code-snippet name="Infinite Scroll with WhenVisible" lang="react">
340+
341+
import { WhenVisible } from '@inertiajs/react'
342+
343+
export default function UsersList({ users }) {
344+
return (
345+
<div>
346+
{users.data.map(user => (
347+
<div key={user.id}>{user.name}</div>
348+
))}
349+
350+
{users.next_page_url && (
351+
<WhenVisible
352+
data="users"
353+
params={{ page: users.current_page + 1 }}
354+
fallback={<div>Loading more...</div>}
355+
/>
356+
)}
357+
</div>
358+
)
359+
}
360+
361+
</code-snippet>
362+
363+
## Common Pitfalls
364+
365+
- Using traditional `<a>` links instead of Inertia's `<Link>` component (breaks SPA behavior)
366+
- Forgetting to add loading states (skeleton screens) when using deferred props
367+
- Not handling the `undefined` state of deferred props before data loads
368+
- Using `<form>` without preventing default submission (use `<Form>` component or `e.preventDefault()`)
369+
- Forgetting to check if `<Form>` component is available in your Inertia version

0 commit comments

Comments
 (0)