@inertiajs/react 2.3.16 → 3.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +986 -532
- package/dist/index.js.map +4 -4
- package/dist/server.js +4 -35
- package/dist/server.js.map +2 -2
- package/package.json +12 -13
- package/resources/boost/guidelines/core.blade.php +3 -0
- package/resources/boost/skills/inertia-react-development/SKILL.blade.php +362 -0
- package/types/App.d.ts +3 -2
- package/types/Deferred.d.ts +4 -1
- package/types/Form.d.ts +10 -19
- package/types/InfiniteScroll.d.ts +2 -1
- package/types/createInertiaApp.d.ts +15 -4
- package/types/index.d.ts +6 -15
- package/types/layoutProps.d.ts +8 -0
- package/types/react.d.ts +0 -1
- package/types/types.d.ts +3 -1
- package/types/useForm.d.ts +10 -12
- package/types/useFormState.d.ts +79 -0
- package/types/useHttp.d.ts +65 -0
- package/dist/index.esm.js +0 -1651
- package/dist/index.esm.js.map +0 -7
- package/dist/server.esm.js +0 -6
- package/dist/server.esm.js.map +0 -7
package/dist/server.js
CHANGED
|
@@ -1,37 +1,6 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __export = (target, all) => {
|
|
9
|
-
for (var name in all)
|
|
10
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
-
};
|
|
12
|
-
var __copyProps = (to, from, except, desc) => {
|
|
13
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
-
for (let key of __getOwnPropNames(from))
|
|
15
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
-
}
|
|
18
|
-
return to;
|
|
19
|
-
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
-
|
|
30
1
|
// src/server.ts
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
module.exports = __toCommonJS(server_exports);
|
|
36
|
-
var import_server = __toESM(require("@inertiajs/core/server"), 1);
|
|
2
|
+
import { default as default2 } from "@inertiajs/core/server";
|
|
3
|
+
export {
|
|
4
|
+
default2 as default
|
|
5
|
+
};
|
|
37
6
|
//# sourceMappingURL=server.js.map
|
package/dist/server.js.map
CHANGED
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/server.ts"],
|
|
4
4
|
"sourcesContent": ["export { default as default } from '@inertiajs/core/server'\n"],
|
|
5
|
-
"mappings": "
|
|
6
|
-
"names": []
|
|
5
|
+
"mappings": ";AAAA,SAAoB,WAAXA,gBAA0B;",
|
|
6
|
+
"names": ["default"]
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inertiajs/react",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0-beta.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "The React adapter for Inertia.js",
|
|
6
6
|
"contributors": [
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"homepage": "https://inertiajs.com/",
|
|
11
11
|
"repository": {
|
|
12
12
|
"type": "git",
|
|
13
|
-
"url": "https://github.com/inertiajs/inertia.git",
|
|
13
|
+
"url": "git+https://github.com/inertiajs/inertia.git",
|
|
14
14
|
"directory": "packages/react"
|
|
15
15
|
},
|
|
16
16
|
"bugs": {
|
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
},
|
|
19
19
|
"files": [
|
|
20
20
|
"dist",
|
|
21
|
-
"types"
|
|
21
|
+
"types",
|
|
22
|
+
"resources"
|
|
22
23
|
],
|
|
23
24
|
"type": "module",
|
|
24
25
|
"main": "dist/index.js",
|
|
@@ -26,13 +27,11 @@
|
|
|
26
27
|
"exports": {
|
|
27
28
|
".": {
|
|
28
29
|
"types": "./types/index.d.ts",
|
|
29
|
-
"import": "./dist/index.
|
|
30
|
-
"require": "./dist/index.js"
|
|
30
|
+
"import": "./dist/index.js"
|
|
31
31
|
},
|
|
32
32
|
"./server": {
|
|
33
33
|
"types": "./types/server.d.ts",
|
|
34
|
-
"import": "./dist/server.
|
|
35
|
-
"require": "./dist/server.js"
|
|
34
|
+
"import": "./dist/server.js"
|
|
36
35
|
}
|
|
37
36
|
},
|
|
38
37
|
"typesVersions": {
|
|
@@ -46,7 +45,7 @@
|
|
|
46
45
|
"@types/react": "^19.2.14",
|
|
47
46
|
"@types/react-dom": "^19.2.3",
|
|
48
47
|
"axios": "^1.13.5",
|
|
49
|
-
"es-check": "^9.
|
|
48
|
+
"es-check": "^9.6.1",
|
|
50
49
|
"esbuild": "^0.27.3",
|
|
51
50
|
"esbuild-node-externals": "^1.20.1",
|
|
52
51
|
"react": "^19.2.4",
|
|
@@ -54,14 +53,14 @@
|
|
|
54
53
|
"typescript": "^5.9.3"
|
|
55
54
|
},
|
|
56
55
|
"peerDependencies": {
|
|
57
|
-
"react": "^
|
|
58
|
-
"react-dom": "^
|
|
56
|
+
"react": "^19.0.0",
|
|
57
|
+
"react-dom": "^19.0.0"
|
|
59
58
|
},
|
|
60
59
|
"dependencies": {
|
|
61
60
|
"@types/lodash-es": "^4.17.12",
|
|
62
|
-
"laravel-precognition": "
|
|
61
|
+
"laravel-precognition": "2.0.0-beta.2",
|
|
63
62
|
"lodash-es": "^4.17.23",
|
|
64
|
-
"@inertiajs/core": "
|
|
63
|
+
"@inertiajs/core": "3.0.0-beta.1"
|
|
65
64
|
},
|
|
66
65
|
"scripts": {
|
|
67
66
|
"build": "pnpm clean && ./build.js && tsc",
|
|
@@ -70,6 +69,6 @@
|
|
|
70
69
|
"dev": "pnpx concurrently -c \"#ffcf00,#3178c6\" \"pnpm dev:build\" \"pnpm dev:types\" --names build,types",
|
|
71
70
|
"dev:build": "./build.js --watch",
|
|
72
71
|
"dev:types": "tsc --watch --preserveWatchOutput",
|
|
73
|
-
"es2020-check": "pnpm build:with-deps && es-check es2020 \"dist/index.
|
|
72
|
+
"es2020-check": "pnpm build:with-deps && es-check es2020 \"dist/index.js\" --checkFeatures --module --noCache --verbose"
|
|
74
73
|
}
|
|
75
74
|
}
|
|
@@ -0,0 +1,362 @@
|
|
|
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
|
+
|
|
13
|
+
## When to Apply
|
|
14
|
+
|
|
15
|
+
Activate this skill when:
|
|
16
|
+
|
|
17
|
+
- Creating or modifying React page components for Inertia
|
|
18
|
+
- Working with forms in React (using `<Form>` or `useForm`)
|
|
19
|
+
- Implementing client-side navigation with `<Link>` or `router`
|
|
20
|
+
- Using v2 features: deferred props, prefetching, WhenVisible, InfiniteScroll, once props, flash data, or polling
|
|
21
|
+
- Building React-specific features with the Inertia protocol
|
|
22
|
+
|
|
23
|
+
## Documentation
|
|
24
|
+
|
|
25
|
+
Use `search-docs` for detailed Inertia v2 React patterns and documentation.
|
|
26
|
+
|
|
27
|
+
## Basic Usage
|
|
28
|
+
|
|
29
|
+
### Page Components Location
|
|
30
|
+
|
|
31
|
+
React page components should be placed in the `{{ $assist->inertia()->pagesDirectory() }}` directory.
|
|
32
|
+
|
|
33
|
+
### Page Component Structure
|
|
34
|
+
|
|
35
|
+
@boostsnippet("Basic React Page Component", "react")
|
|
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
|
+
@endboostsnippet
|
|
47
|
+
|
|
48
|
+
## Client-Side Navigation
|
|
49
|
+
|
|
50
|
+
### Basic Link Component
|
|
51
|
+
|
|
52
|
+
Use `<Link>` for client-side navigation instead of traditional `<a>` tags:
|
|
53
|
+
|
|
54
|
+
@boostsnippet("Inertia React Navigation", "react")
|
|
55
|
+
import { Link, router } from '@inertiajs/react'
|
|
56
|
+
|
|
57
|
+
<Link href="/">Home</Link>
|
|
58
|
+
<Link href="/users">Users</Link>
|
|
59
|
+
<Link href={`/users/${user.id}`}>View User</Link>
|
|
60
|
+
@endboostsnippet
|
|
61
|
+
|
|
62
|
+
### Link with Method
|
|
63
|
+
|
|
64
|
+
@boostsnippet("Link with POST Method", "react")
|
|
65
|
+
import { Link } from '@inertiajs/react'
|
|
66
|
+
|
|
67
|
+
<Link href="/logout" method="post" as="button">
|
|
68
|
+
Logout
|
|
69
|
+
</Link>
|
|
70
|
+
@endboostsnippet
|
|
71
|
+
|
|
72
|
+
### Prefetching
|
|
73
|
+
|
|
74
|
+
Prefetch pages to improve perceived performance:
|
|
75
|
+
|
|
76
|
+
@boostsnippet("Prefetch on Hover", "react")
|
|
77
|
+
import { Link } from '@inertiajs/react'
|
|
78
|
+
|
|
79
|
+
<Link href="/users" prefetch>
|
|
80
|
+
Users
|
|
81
|
+
</Link>
|
|
82
|
+
@endboostsnippet
|
|
83
|
+
|
|
84
|
+
### Programmatic Navigation
|
|
85
|
+
|
|
86
|
+
@boostsnippet("Router Visit", "react")
|
|
87
|
+
import { router } from '@inertiajs/react'
|
|
88
|
+
|
|
89
|
+
function handleClick() {
|
|
90
|
+
router.visit('/users')
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Or with options
|
|
94
|
+
router.visit('/users', {
|
|
95
|
+
method: 'post',
|
|
96
|
+
data: { name: 'John' },
|
|
97
|
+
onSuccess: () => console.log('Success!'),
|
|
98
|
+
})
|
|
99
|
+
@endboostsnippet
|
|
100
|
+
|
|
101
|
+
## Form Handling
|
|
102
|
+
|
|
103
|
+
@if($assist->inertia()->hasFormComponent())
|
|
104
|
+
### Form Component (Recommended)
|
|
105
|
+
|
|
106
|
+
The recommended way to build forms is with the `<Form>` component:
|
|
107
|
+
|
|
108
|
+
@boostsnippet("Form Component Example", "react")
|
|
109
|
+
import { Form } from '@inertiajs/react'
|
|
110
|
+
|
|
111
|
+
export default function CreateUser() {
|
|
112
|
+
return (
|
|
113
|
+
<Form action="/users" method="post">
|
|
114
|
+
{({ errors, processing, wasSuccessful }) => (
|
|
115
|
+
<>
|
|
116
|
+
<input type="text" name="name" />
|
|
117
|
+
{errors.name && <div>{errors.name}</div>}
|
|
118
|
+
|
|
119
|
+
<input type="email" name="email" />
|
|
120
|
+
{errors.email && <div>{errors.email}</div>}
|
|
121
|
+
|
|
122
|
+
<button type="submit" disabled={processing}>
|
|
123
|
+
{processing ? 'Creating...' : 'Create User'}
|
|
124
|
+
</button>
|
|
125
|
+
|
|
126
|
+
{wasSuccessful && <div>User created!</div>}
|
|
127
|
+
</>
|
|
128
|
+
)}
|
|
129
|
+
</Form>
|
|
130
|
+
)
|
|
131
|
+
}
|
|
132
|
+
@endboostsnippet
|
|
133
|
+
|
|
134
|
+
### Form Component With All Props
|
|
135
|
+
|
|
136
|
+
@boostsnippet("Form Component Full Example", "react")
|
|
137
|
+
import { Form } from '@inertiajs/react'
|
|
138
|
+
|
|
139
|
+
<Form action="/users" method="post">
|
|
140
|
+
{({
|
|
141
|
+
errors,
|
|
142
|
+
hasErrors,
|
|
143
|
+
processing,
|
|
144
|
+
progress,
|
|
145
|
+
wasSuccessful,
|
|
146
|
+
recentlySuccessful,
|
|
147
|
+
clearErrors,
|
|
148
|
+
resetAndClearErrors,
|
|
149
|
+
defaults,
|
|
150
|
+
isDirty,
|
|
151
|
+
reset,
|
|
152
|
+
submit
|
|
153
|
+
}) => (
|
|
154
|
+
<>
|
|
155
|
+
<input type="text" name="name" defaultValue={defaults.name} />
|
|
156
|
+
{errors.name && <div>{errors.name}</div>}
|
|
157
|
+
|
|
158
|
+
<button type="submit" disabled={processing}>
|
|
159
|
+
{processing ? 'Saving...' : 'Save'}
|
|
160
|
+
</button>
|
|
161
|
+
|
|
162
|
+
{progress && (
|
|
163
|
+
<progress value={progress.percentage} max="100">
|
|
164
|
+
{progress.percentage}%
|
|
165
|
+
</progress>
|
|
166
|
+
)}
|
|
167
|
+
|
|
168
|
+
{wasSuccessful && <div>Saved!</div>}
|
|
169
|
+
</>
|
|
170
|
+
)}
|
|
171
|
+
</Form>
|
|
172
|
+
@endboostsnippet
|
|
173
|
+
|
|
174
|
+
@if($assist->inertia()->hasFormComponentResets())
|
|
175
|
+
### Form Component Reset Props
|
|
176
|
+
|
|
177
|
+
The `<Form>` component supports automatic resetting:
|
|
178
|
+
|
|
179
|
+
- `resetOnError` - Reset form data when the request fails
|
|
180
|
+
- `resetOnSuccess` - Reset form data when the request succeeds
|
|
181
|
+
- `setDefaultsOnSuccess` - Update default values on success
|
|
182
|
+
|
|
183
|
+
Use the `search-docs` tool with a query of `form component resetting` for detailed guidance.
|
|
184
|
+
|
|
185
|
+
@boostsnippet("Form with Reset Props", "react")
|
|
186
|
+
import { Form } from '@inertiajs/react'
|
|
187
|
+
|
|
188
|
+
<Form
|
|
189
|
+
action="/users"
|
|
190
|
+
method="post"
|
|
191
|
+
resetOnSuccess
|
|
192
|
+
setDefaultsOnSuccess
|
|
193
|
+
>
|
|
194
|
+
{({ errors, processing, wasSuccessful }) => (
|
|
195
|
+
<>
|
|
196
|
+
<input type="text" name="name" />
|
|
197
|
+
{errors.name && <div>{errors.name}</div>}
|
|
198
|
+
|
|
199
|
+
<button type="submit" disabled={processing}>
|
|
200
|
+
Submit
|
|
201
|
+
</button>
|
|
202
|
+
</>
|
|
203
|
+
)}
|
|
204
|
+
</Form>
|
|
205
|
+
@endboostsnippet
|
|
206
|
+
@else
|
|
207
|
+
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.
|
|
208
|
+
@endif
|
|
209
|
+
|
|
210
|
+
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.
|
|
211
|
+
|
|
212
|
+
@endif
|
|
213
|
+
|
|
214
|
+
### `useForm` Hook
|
|
215
|
+
|
|
216
|
+
@if($assist->inertia()->hasFormComponent() === false)
|
|
217
|
+
For Inertia v2.0.x: Build forms using the `useForm` helper as the `<Form>` component is not available until v2.1.0+.
|
|
218
|
+
@else
|
|
219
|
+
For more programmatic control or to follow existing conventions, use the `useForm` hook:
|
|
220
|
+
@endif
|
|
221
|
+
|
|
222
|
+
@boostsnippet("useForm Hook Example", "react")
|
|
223
|
+
import { useForm } from '@inertiajs/react'
|
|
224
|
+
|
|
225
|
+
export default function CreateUser() {
|
|
226
|
+
const { data, setData, post, processing, errors, reset } = useForm({
|
|
227
|
+
name: '',
|
|
228
|
+
email: '',
|
|
229
|
+
password: '',
|
|
230
|
+
})
|
|
231
|
+
|
|
232
|
+
function submit(e) {
|
|
233
|
+
e.preventDefault()
|
|
234
|
+
post('/users', {
|
|
235
|
+
onSuccess: () => reset('password'),
|
|
236
|
+
})
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return (
|
|
240
|
+
<form onSubmit={submit}>
|
|
241
|
+
<input
|
|
242
|
+
type="text"
|
|
243
|
+
value={data.name}
|
|
244
|
+
onChange={e => setData('name', e.target.value)}
|
|
245
|
+
/>
|
|
246
|
+
{errors.name && <div>{errors.name}</div>}
|
|
247
|
+
|
|
248
|
+
<input
|
|
249
|
+
type="email"
|
|
250
|
+
value={data.email}
|
|
251
|
+
onChange={e => setData('email', e.target.value)}
|
|
252
|
+
/>
|
|
253
|
+
{errors.email && <div>{errors.email}</div>}
|
|
254
|
+
|
|
255
|
+
<input
|
|
256
|
+
type="password"
|
|
257
|
+
value={data.password}
|
|
258
|
+
onChange={e => setData('password', e.target.value)}
|
|
259
|
+
/>
|
|
260
|
+
{errors.password && <div>{errors.password}</div>}
|
|
261
|
+
|
|
262
|
+
<button type="submit" disabled={processing}>
|
|
263
|
+
Create User
|
|
264
|
+
</button>
|
|
265
|
+
</form>
|
|
266
|
+
)
|
|
267
|
+
}
|
|
268
|
+
@endboostsnippet
|
|
269
|
+
|
|
270
|
+
## Inertia v2 Features
|
|
271
|
+
|
|
272
|
+
### Deferred Props
|
|
273
|
+
|
|
274
|
+
Use deferred props to load data after initial page render:
|
|
275
|
+
|
|
276
|
+
@boostsnippet("Deferred Props with Empty State", "react")
|
|
277
|
+
export default function UsersIndex({ users }) {
|
|
278
|
+
// users will be undefined initially, then populated
|
|
279
|
+
return (
|
|
280
|
+
<div>
|
|
281
|
+
<h1>Users</h1>
|
|
282
|
+
{!users ? (
|
|
283
|
+
<div className="animate-pulse">
|
|
284
|
+
<div className="h-4 bg-gray-200 rounded w-3/4 mb-2"></div>
|
|
285
|
+
<div className="h-4 bg-gray-200 rounded w-1/2"></div>
|
|
286
|
+
</div>
|
|
287
|
+
) : (
|
|
288
|
+
<ul>
|
|
289
|
+
{users.map(user => (
|
|
290
|
+
<li key={user.id}>{user.name}</li>
|
|
291
|
+
))}
|
|
292
|
+
</ul>
|
|
293
|
+
)}
|
|
294
|
+
</div>
|
|
295
|
+
)
|
|
296
|
+
}
|
|
297
|
+
@endboostsnippet
|
|
298
|
+
|
|
299
|
+
### Polling
|
|
300
|
+
|
|
301
|
+
Automatically refresh data at intervals:
|
|
302
|
+
|
|
303
|
+
@boostsnippet("Polling Example", "react")
|
|
304
|
+
import { router } from '@inertiajs/react'
|
|
305
|
+
import { useEffect } from 'react'
|
|
306
|
+
|
|
307
|
+
export default function Dashboard({ stats }) {
|
|
308
|
+
useEffect(() => {
|
|
309
|
+
const interval = setInterval(() => {
|
|
310
|
+
router.reload({ only: ['stats'] })
|
|
311
|
+
}, 5000) // Poll every 5 seconds
|
|
312
|
+
|
|
313
|
+
return () => clearInterval(interval)
|
|
314
|
+
}, [])
|
|
315
|
+
|
|
316
|
+
return (
|
|
317
|
+
<div>
|
|
318
|
+
<h1>Dashboard</h1>
|
|
319
|
+
<div>Active Users: {stats.activeUsers}</div>
|
|
320
|
+
</div>
|
|
321
|
+
)
|
|
322
|
+
}
|
|
323
|
+
@endboostsnippet
|
|
324
|
+
|
|
325
|
+
### WhenVisible
|
|
326
|
+
|
|
327
|
+
Lazy-load a prop when an element scrolls into view. Useful for deferring expensive data that sits below the fold:
|
|
328
|
+
|
|
329
|
+
@boostsnippet("WhenVisible Example", "react")
|
|
330
|
+
import { WhenVisible } from '@inertiajs/react'
|
|
331
|
+
|
|
332
|
+
export default function Dashboard({ stats }) {
|
|
333
|
+
return (
|
|
334
|
+
<div>
|
|
335
|
+
<h1>Dashboard</h1>
|
|
336
|
+
|
|
337
|
+
{/* stats prop is loaded only when this section scrolls into view */}
|
|
338
|
+
<WhenVisible data="stats" buffer={200} fallback={<div className="animate-pulse">Loading stats...</div>}>
|
|
339
|
+
{({ fetching }) => (
|
|
340
|
+
<div>
|
|
341
|
+
<p>Total Users: {stats.total_users}</p>
|
|
342
|
+
<p>Revenue: {stats.revenue}</p>
|
|
343
|
+
{fetching && <span>Refreshing...</span>}
|
|
344
|
+
</div>
|
|
345
|
+
)}
|
|
346
|
+
</WhenVisible>
|
|
347
|
+
</div>
|
|
348
|
+
)
|
|
349
|
+
}
|
|
350
|
+
@endboostsnippet
|
|
351
|
+
|
|
352
|
+
## Server-Side Patterns
|
|
353
|
+
|
|
354
|
+
Server-side patterns (Inertia::render, props, middleware) are covered in inertia-laravel guidelines.
|
|
355
|
+
|
|
356
|
+
## Common Pitfalls
|
|
357
|
+
|
|
358
|
+
- Using traditional `<a>` links instead of Inertia's `<Link>` component (breaks SPA behavior)
|
|
359
|
+
- Forgetting to add loading states (skeleton screens) when using deferred props
|
|
360
|
+
- Not handling the `undefined` state of deferred props before data loads
|
|
361
|
+
- Using `<form>` without preventing default submission (use `<Form>` component or `e.preventDefault()`)
|
|
362
|
+
- Forgetting to check if `<Form>` component is available in your Inertia version
|
package/types/App.d.ts
CHANGED
|
@@ -9,12 +9,13 @@ export interface InertiaAppProps<SharedProps extends PageProps = PageProps> {
|
|
|
9
9
|
}) => ReactNode;
|
|
10
10
|
initialPage: Page<SharedProps>;
|
|
11
11
|
initialComponent?: ReactComponent;
|
|
12
|
-
resolveComponent?: (name: string) => ReactComponent | Promise<ReactComponent>;
|
|
12
|
+
resolveComponent?: (name: string, page?: Page) => ReactComponent | Promise<ReactComponent>;
|
|
13
13
|
titleCallback?: HeadManagerTitleCallback;
|
|
14
14
|
onHeadUpdate?: HeadManagerOnUpdateCallback;
|
|
15
|
+
defaultLayout?: (name: string, page: Page) => unknown;
|
|
15
16
|
}
|
|
16
17
|
export type InertiaApp = FunctionComponent<InertiaAppProps>;
|
|
17
|
-
declare function App<SharedProps extends PageProps = PageProps>({ children, initialPage, initialComponent, resolveComponent, titleCallback, onHeadUpdate, }: InertiaAppProps<SharedProps>): import("react").FunctionComponentElement<import("react").ProviderProps<import("@inertiajs/core").HeadManager | null>>;
|
|
18
|
+
declare function App<SharedProps extends PageProps = PageProps>({ children, initialPage, initialComponent, resolveComponent, titleCallback, onHeadUpdate, defaultLayout, }: InertiaAppProps<SharedProps>): import("react").FunctionComponentElement<import("react").ProviderProps<import("@inertiajs/core").HeadManager | null>>;
|
|
18
19
|
declare namespace App {
|
|
19
20
|
var displayName: string;
|
|
20
21
|
}
|
package/types/Deferred.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
|
+
interface DeferredSlotProps {
|
|
3
|
+
reloading: boolean;
|
|
4
|
+
}
|
|
2
5
|
interface DeferredProps {
|
|
3
|
-
children: ReactNode | (() => ReactNode);
|
|
6
|
+
children: ReactNode | ((props: DeferredSlotProps) => ReactNode);
|
|
4
7
|
fallback: ReactNode | (() => ReactNode);
|
|
5
8
|
data: string | string[];
|
|
6
9
|
}
|
package/types/Form.d.ts
CHANGED
|
@@ -1,20 +1,11 @@
|
|
|
1
|
-
import { FormComponentRef, FormComponentSlotProps
|
|
1
|
+
import { FormComponentProps, FormComponentRef, FormComponentSlotProps } from '@inertiajs/core';
|
|
2
2
|
import React, { ReactNode } from 'react';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
setDefaultsOnSuccess?: boolean;
|
|
13
|
-
validateFiles?: boolean;
|
|
14
|
-
validationTimeout?: number;
|
|
15
|
-
withAllErrors?: boolean | null;
|
|
16
|
-
} & Omit<React.FormHTMLAttributes<HTMLFormElement>, "children" | "method" | "headers" | "errorBag" | "queryStringArrayFormat" | "showProgress" | "invalidateCacheTags" | "onCancelToken" | "onBefore" | "onBeforeUpdate" | "onStart" | "onProgress" | "onFinish" | "onCancel" | "onSuccess" | "onError" | "onFlash" | "withAllErrors" | "options" | "action" | "transform" | "onSubmitComplete" | "disableWhileProcessing" | "resetOnSuccess" | "resetOnError" | "setDefaultsOnSuccess" | "validateFiles" | "validationTimeout"> & Omit<React.AllHTMLAttributes<HTMLFormElement>, "children" | "method" | "headers" | "errorBag" | "queryStringArrayFormat" | "showProgress" | "invalidateCacheTags" | "onCancelToken" | "onBefore" | "onBeforeUpdate" | "onStart" | "onProgress" | "onFinish" | "onCancel" | "onSuccess" | "onError" | "onFlash" | "withAllErrors" | "options" | "action" | "transform" | "onSubmitComplete" | "disableWhileProcessing" | "resetOnSuccess" | "resetOnError" | "setDefaultsOnSuccess" | "validateFiles" | "validationTimeout"> & {
|
|
17
|
-
children: ReactNode | ((props: FormComponentSlotProps) => ReactNode);
|
|
18
|
-
} & React.RefAttributes<FormComponentSlotProps>>;
|
|
19
|
-
export declare function useFormContext(): FormComponentRef | undefined;
|
|
20
|
-
export default Form;
|
|
3
|
+
type FormProps<TForm extends object = Record<string, any>> = FormComponentProps & Omit<React.FormHTMLAttributes<HTMLFormElement>, keyof FormComponentProps | 'children'> & Omit<React.AllHTMLAttributes<HTMLFormElement>, keyof FormComponentProps | 'children'> & {
|
|
4
|
+
children: ReactNode | ((props: FormComponentSlotProps<TForm>) => ReactNode);
|
|
5
|
+
};
|
|
6
|
+
export declare function useFormContext<TForm extends object = Record<string, any>>(): FormComponentRef<TForm> | undefined;
|
|
7
|
+
declare const _default: {
|
|
8
|
+
<TForm extends object = Record<string, any>>(props: FormProps<TForm> & React.RefAttributes<FormComponentRef<TForm>>): React.ReactElement;
|
|
9
|
+
displayName: string;
|
|
10
|
+
};
|
|
11
|
+
export default _default;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { InfiniteScrollActionSlotProps, InfiniteScrollComponentBaseProps, InfiniteScrollRef, InfiniteScrollSlotProps } from '@inertiajs/core';
|
|
1
|
+
import { InfiniteScrollActionSlotProps, InfiniteScrollComponentBaseProps, InfiniteScrollRef, InfiniteScrollSlotProps, ReloadOptions } from '@inertiajs/core';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
interface ComponentProps extends InfiniteScrollComponentBaseProps, Omit<React.HTMLAttributes<HTMLElement>, keyof InfiniteScrollComponentBaseProps | 'children'> {
|
|
4
4
|
children?: React.ReactNode | ((props: InfiniteScrollSlotProps) => React.ReactNode);
|
|
@@ -8,6 +8,7 @@ interface ComponentProps extends InfiniteScrollComponentBaseProps, Omit<React.HT
|
|
|
8
8
|
previous?: React.ReactNode | ((props: InfiniteScrollActionSlotProps) => React.ReactNode);
|
|
9
9
|
next?: React.ReactNode | ((props: InfiniteScrollActionSlotProps) => React.ReactNode);
|
|
10
10
|
loading?: React.ReactNode | ((props: InfiniteScrollActionSlotProps) => React.ReactNode);
|
|
11
|
+
params?: ReloadOptions;
|
|
11
12
|
onlyNext?: boolean;
|
|
12
13
|
onlyPrevious?: boolean;
|
|
13
14
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CreateInertiaAppOptionsForCSR, CreateInertiaAppOptionsForSSR, InertiaAppSSRResponse, PageProps } from '@inertiajs/core';
|
|
1
|
+
import { CreateInertiaAppOptions, CreateInertiaAppOptionsForCSR, CreateInertiaAppOptionsForSSR, InertiaAppSSRResponse, Page, PageProps } from '@inertiajs/core';
|
|
2
2
|
import { ReactElement } from 'react';
|
|
3
3
|
import { renderToString } from 'react-dom/server';
|
|
4
4
|
import { InertiaAppProps, type InertiaApp } from './App';
|
|
@@ -8,13 +8,24 @@ export type SetupOptions<ElementType, SharedProps extends PageProps> = {
|
|
|
8
8
|
App: InertiaApp;
|
|
9
9
|
props: InertiaAppProps<SharedProps>;
|
|
10
10
|
};
|
|
11
|
-
type ComponentResolver = (name: string) => ReactComponent | Promise<ReactComponent> | {
|
|
11
|
+
type ComponentResolver = (name: string, page?: Page) => ReactComponent | Promise<ReactComponent> | {
|
|
12
12
|
default: ReactComponent;
|
|
13
|
-
}
|
|
14
|
-
type InertiaAppOptionsForCSR<SharedProps extends PageProps> = CreateInertiaAppOptionsForCSR<SharedProps, ComponentResolver, SetupOptions<HTMLElement, SharedProps>, void, ReactInertiaAppConfig
|
|
13
|
+
};
|
|
14
|
+
type InertiaAppOptionsForCSR<SharedProps extends PageProps> = CreateInertiaAppOptionsForCSR<SharedProps, ComponentResolver, SetupOptions<HTMLElement, SharedProps>, void, ReactInertiaAppConfig> & {
|
|
15
|
+
strictMode?: undefined;
|
|
16
|
+
};
|
|
15
17
|
type InertiaAppOptionsForSSR<SharedProps extends PageProps> = CreateInertiaAppOptionsForSSR<SharedProps, ComponentResolver, SetupOptions<null, SharedProps>, ReactElement, ReactInertiaAppConfig> & {
|
|
16
18
|
render: typeof renderToString;
|
|
19
|
+
strictMode?: undefined;
|
|
20
|
+
};
|
|
21
|
+
type InertiaAppOptionsAuto<SharedProps extends PageProps> = CreateInertiaAppOptions<ComponentResolver, SetupOptions<HTMLElement | null, SharedProps>, ReactElement | void, ReactInertiaAppConfig> & {
|
|
22
|
+
page?: Page<SharedProps>;
|
|
23
|
+
render?: undefined;
|
|
24
|
+
strictMode?: boolean;
|
|
17
25
|
};
|
|
26
|
+
type RenderToString = (element: ReactElement) => string;
|
|
27
|
+
type RenderFunction<SharedProps extends PageProps> = (page: Page<SharedProps>, renderToString: RenderToString) => Promise<InertiaAppSSRResponse>;
|
|
18
28
|
export default function createInertiaApp<SharedProps extends PageProps = PageProps>(options: InertiaAppOptionsForCSR<SharedProps>): Promise<void>;
|
|
19
29
|
export default function createInertiaApp<SharedProps extends PageProps = PageProps>(options: InertiaAppOptionsForSSR<SharedProps>): Promise<InertiaAppSSRResponse>;
|
|
30
|
+
export default function createInertiaApp<SharedProps extends PageProps = PageProps>(options?: InertiaAppOptionsAuto<SharedProps>): Promise<void | RenderFunction<SharedProps>>;
|
|
20
31
|
export {};
|
package/types/index.d.ts
CHANGED
|
@@ -1,28 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
start(): void;
|
|
4
|
-
reveal(force?: boolean): void;
|
|
5
|
-
hide(): void;
|
|
6
|
-
set(status: number): void;
|
|
7
|
-
finish(): void;
|
|
8
|
-
reset(): void;
|
|
9
|
-
remove(): void;
|
|
10
|
-
isStarted(): boolean;
|
|
11
|
-
getStatus(): number | null;
|
|
12
|
-
};
|
|
13
|
-
export declare const router: import("@inertiajs/core").Router;
|
|
1
|
+
import type { ReactInertiaAppConfig } from './types';
|
|
2
|
+
export { http, progress, router } from '@inertiajs/core';
|
|
14
3
|
export { default as App } from './App';
|
|
15
4
|
export { default as createInertiaApp } from './createInertiaApp';
|
|
16
5
|
export { default as Deferred } from './Deferred';
|
|
17
6
|
export { default as Form, useFormContext } from './Form';
|
|
18
7
|
export { default as Head } from './Head';
|
|
19
8
|
export { default as InfiniteScroll } from './InfiniteScroll';
|
|
9
|
+
export { resetLayoutProps, setLayoutProps, setLayoutPropsFor, useLayoutProps } from './layoutProps';
|
|
20
10
|
export { InertiaLinkProps, default as Link } from './Link';
|
|
21
11
|
export { ReactComponent as ResolvedComponent } from './types';
|
|
22
|
-
export { InertiaFormProps, InertiaPrecognitiveFormProps, SetDataAction, SetDataByKeyValuePair, SetDataByMethod, SetDataByObject, default as useForm, } from './useForm';
|
|
12
|
+
export { InertiaForm, InertiaFormProps, InertiaPrecognitiveFormProps, SetDataAction, SetDataByKeyValuePair, SetDataByMethod, SetDataByObject, default as useForm, } from './useForm';
|
|
13
|
+
export { default as useHttp } from './useHttp';
|
|
23
14
|
export { default as usePage } from './usePage';
|
|
24
15
|
export { default as usePoll } from './usePoll';
|
|
25
16
|
export { default as usePrefetch } from './usePrefetch';
|
|
26
17
|
export { default as useRemember } from './useRemember';
|
|
27
18
|
export { default as WhenVisible } from './WhenVisible';
|
|
28
|
-
export declare const config: import("@inertiajs/core").Config<import("@inertiajs/core").InertiaAppConfig>;
|
|
19
|
+
export declare const config: import("@inertiajs/core").Config<import("@inertiajs/core").InertiaAppConfig & ReactInertiaAppConfig>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare function setLayoutProps(props: Record<string, unknown>): void;
|
|
2
|
+
export declare function setLayoutPropsFor(name: string, props: Record<string, unknown>): void;
|
|
3
|
+
export declare function resetLayoutProps(): void;
|
|
4
|
+
export declare const LayoutPropsContext: import("react").Context<{
|
|
5
|
+
staticProps: Record<string, unknown>;
|
|
6
|
+
name?: string;
|
|
7
|
+
}>;
|
|
8
|
+
export declare function useLayoutProps<T extends Record<string, unknown>>(defaults: T): T;
|
package/types/react.d.ts
CHANGED
package/types/types.d.ts
CHANGED
|
@@ -8,4 +8,6 @@ export type ReactComponent = ComponentType<any> & {
|
|
|
8
8
|
layout?: LayoutComponent | LayoutComponent[] | LayoutFunction;
|
|
9
9
|
};
|
|
10
10
|
export type ReactPageHandlerArgs = Parameters<PageHandler<ComponentType>>[0];
|
|
11
|
-
export type ReactInertiaAppConfig = {
|
|
11
|
+
export type ReactInertiaAppConfig = {
|
|
12
|
+
strictMode?: boolean;
|
|
13
|
+
};
|