0
# Forms and Navigation
1
2
Enhanced form handling and navigation components with progressive enhancement, prefetching capabilities, and seamless client-server communication.
3
4
## Capabilities
5
6
### Form
7
8
Enhanced HTML form component that provides progressive enhancement and seamless integration with Remix's action system.
9
10
```typescript { .api }
11
/**
12
* Enhanced HTML form component with progressive enhancement
13
* Automatically handles form submission, validation, and server communication
14
* @param props - Form configuration and HTML form attributes
15
* @returns React form element with enhanced functionality
16
*/
17
function Form(props: RemixFormProps): ReactElement;
18
19
interface RemixFormProps extends Omit<FormHTMLAttributes<HTMLFormElement>, "onSubmit"> {
20
/** HTTP method for form submission */
21
method?: "get" | "post" | "put" | "patch" | "delete";
22
/** URL to submit the form to (defaults to current route) */
23
action?: string;
24
/** Route discovery behavior */
25
discover?: "render" | "none";
26
/** Encoding type for form data */
27
encType?: "application/x-www-form-urlencoded" | "multipart/form-data" | "text/plain";
28
/** Whether to replace the current history entry instead of pushing a new one */
29
replace?: boolean;
30
/** Whether to prevent automatic scroll restoration after form submission */
31
preventScrollReset?: boolean;
32
/** Whether to trigger a full page reload instead of client-side handling */
33
reloadDocument?: boolean;
34
/** Whether to trigger navigation after successful submission */
35
navigate?: boolean;
36
/** Callback for form submission */
37
onSubmit?: (event: React.FormEvent<HTMLFormElement>) => void;
38
}
39
```
40
41
**Usage Examples:**
42
43
```typescript
44
import { Form } from "@remix-run/react";
45
46
// Basic form with POST action
47
function ContactForm() {
48
return (
49
<Form method="post">
50
<input type="email" name="email" required />
51
<textarea name="message" required />
52
<button type="submit">Send Message</button>
53
</Form>
54
);
55
}
56
57
// Form with file upload
58
function UploadForm() {
59
return (
60
<Form method="post" encType="multipart/form-data">
61
<input type="file" name="document" accept=".pdf,.doc" />
62
<button type="submit">Upload</button>
63
</Form>
64
);
65
}
66
67
// Form with custom submission handling
68
function SearchForm() {
69
return (
70
<Form
71
method="get"
72
action="/search"
73
preventScrollReset
74
onSubmit={(event) => {
75
// Optional custom handling before submission
76
console.log("Submitting search...");
77
}}
78
>
79
<input type="search" name="q" placeholder="Search..." />
80
<button type="submit">Search</button>
81
</Form>
82
);
83
}
84
```
85
86
### Link
87
88
Enhanced anchor tag component with prefetching capabilities and client-side navigation.
89
90
```typescript { .api }
91
/**
92
* Enhanced anchor tag with prefetching and client-side navigation
93
* Automatically handles client-side routing and resource prefetching
94
* @param props - Link configuration and HTML anchor attributes
95
* @returns React anchor element with enhanced functionality
96
*/
97
function Link(props: RemixLinkProps): ReactElement;
98
99
interface RemixLinkProps extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, "href"> {
100
/** URL to navigate to */
101
to: string | Partial<Path>;
102
/** Route discovery behavior */
103
discover?: "render" | "none";
104
/** Whether to prefetch the route data and assets */
105
prefetch?: "none" | "intent" | "render" | "viewport";
106
/** Whether to replace the current history entry */
107
replace?: boolean;
108
/** State object to pass with the navigation */
109
state?: any;
110
/** Whether to prevent the scroll from resetting to the top */
111
preventScrollReset?: boolean;
112
/** Relative path resolution behavior */
113
relative?: "route" | "path";
114
/** Whether to reload the document instead of client-side navigation */
115
reloadDocument?: boolean;
116
/** Function to determine if the link should be prefetched */
117
unstable_viewTransition?: boolean;
118
}
119
```
120
121
**Usage Examples:**
122
123
```typescript
124
import { Link } from "@remix-run/react";
125
126
// Basic navigation link
127
function Navigation() {
128
return (
129
<nav>
130
<Link to="/">Home</Link>
131
<Link to="/about">About</Link>
132
<Link to="/contact">Contact</Link>
133
</nav>
134
);
135
}
136
137
// Link with prefetching
138
function ProductCard({ product }) {
139
return (
140
<div>
141
<h3>{product.name}</h3>
142
<Link
143
to={`/products/${product.id}`}
144
prefetch="intent"
145
state={{ from: "catalog" }}
146
>
147
View Details
148
</Link>
149
</div>
150
);
151
}
152
153
// External link with document reload
154
function ExternalLink() {
155
return (
156
<Link
157
to="https://example.com"
158
reloadDocument
159
target="_blank"
160
rel="noopener noreferrer"
161
>
162
External Site
163
</Link>
164
);
165
}
166
```
167
168
### NavLink
169
170
Navigation link component with automatic active state styling and aria attributes.
171
172
```typescript { .api }
173
/**
174
* Navigation link with automatic active state styling
175
* Automatically applies active classes and aria attributes based on current location
176
* @param props - NavLink configuration and HTML anchor attributes
177
* @returns React anchor element with active state functionality
178
*/
179
function NavLink(props: RemixNavLinkProps): ReactElement;
180
181
interface RemixNavLinkProps extends RemixLinkProps {
182
/** Function to determine active state styling */
183
className?: string | ((props: { isActive: boolean; isPending: boolean }) => string);
184
/** Function to determine active state inline styles */
185
style?: CSSProperties | ((props: { isActive: boolean; isPending: boolean }) => CSSProperties);
186
/** Function to determine active state for child content */
187
children?: ReactNode | ((props: { isActive: boolean; isPending: boolean }) => ReactNode);
188
/** Whether the link should match the end of the path exactly */
189
end?: boolean;
190
/** Case sensitivity for path matching */
191
caseSensitive?: boolean;
192
}
193
```
194
195
**Usage Examples:**
196
197
```typescript
198
import { NavLink } from "@remix-run/react";
199
200
// Basic navigation with active styling
201
function MainNavigation() {
202
return (
203
<nav>
204
<NavLink
205
to="/"
206
className={({ isActive }) =>
207
isActive ? "nav-link active" : "nav-link"
208
}
209
end
210
>
211
Home
212
</NavLink>
213
<NavLink
214
to="/blog"
215
style={({ isActive, isPending }) => ({
216
color: isActive ? "red" : isPending ? "orange" : "blue",
217
})}
218
>
219
Blog
220
</NavLink>
221
</nav>
222
);
223
}
224
225
// Dynamic content based on active state
226
function SidebarLink({ to, children }) {
227
return (
228
<NavLink to={to}>
229
{({ isActive, isPending }) => (
230
<>
231
{isActive && <span>👉 </span>}
232
{children}
233
{isPending && <span> ⏳</span>}
234
</>
235
)}
236
</NavLink>
237
);
238
}
239
```
240
241
### PrefetchPageLinks
242
243
Component for prefetching page resources to improve navigation performance.
244
245
```typescript { .api }
246
/**
247
* Prefetches page resources for improved navigation performance
248
* Loads route modules and data for specified pages
249
* @param props - Prefetch configuration
250
* @returns React element containing prefetch link tags
251
*/
252
function PrefetchPageLinks(props: PrefetchPageLinksProps): ReactElement;
253
254
interface PrefetchPageLinksProps {
255
/** Page path to prefetch */
256
page: string;
257
}
258
```
259
260
**Usage Example:**
261
262
```typescript
263
import { PrefetchPageLinks } from "@remix-run/react";
264
265
// Prefetch critical pages
266
function App() {
267
return (
268
<html>
269
<head>
270
<Meta />
271
<Links />
272
{/* Prefetch commonly accessed pages */}
273
<PrefetchPageLinks page="/dashboard" />
274
<PrefetchPageLinks page="/profile" />
275
</head>
276
<body>{/* app content */}</body>
277
</html>
278
);
279
}
280
```
281
282
## Type Definitions
283
284
### Path Object
285
286
```typescript { .api }
287
interface Path {
288
/** The URL pathname */
289
pathname: string;
290
/** The URL search string */
291
search: string;
292
/** The URL hash fragment */
293
hash: string;
294
}
295
```
296
297
### Prefetch Options
298
299
```typescript { .api }
300
type PrefetchBehavior =
301
| "none" // No prefetching
302
| "intent" // Prefetch when user shows intent to navigate (hover, focus)
303
| "render" // Prefetch when the link is rendered
304
| "viewport"; // Prefetch when the link enters the viewport
305
```
306
307
## Implementation Notes
308
309
- **Progressive Enhancement**: All form and navigation components work without JavaScript
310
- **Prefetching**: Link prefetching improves perceived performance by loading resources in advance
311
- **Form Validation**: Form component integrates with browser validation and server-side validation
312
- **Error Handling**: Forms automatically handle server errors and display appropriate feedback
313
- **Accessibility**: All components include proper ARIA attributes and keyboard navigation support
314
- **SEO**: Links and forms are crawlable by search engines even without JavaScript execution