0
# Navigation
1
2
Link components and programmatic navigation functions for moving between routes with accessibility features and state management.
3
4
## Capabilities
5
6
### Link Component
7
8
Accessible navigation link component with automatic active state detection and focus management.
9
10
```javascript { .api }
11
/**
12
* Accessible navigation link with active state detection and ref forwarding
13
* @param props - Link configuration and standard anchor props
14
* @param ref - Forwarded ref to the anchor element
15
*/
16
const Link: React.ForwardRefExoticComponent<{
17
to: string;
18
state?: any;
19
replace?: boolean;
20
getProps?: (props: LinkGetPropsArgument) => object;
21
innerRef?: React.Ref<HTMLAnchorElement>;
22
} & React.AnchorHTMLAttributes<HTMLAnchorElement> & React.RefAttributes<HTMLAnchorElement>>;
23
24
interface LinkGetPropsArgument {
25
isCurrent: boolean;
26
isPartiallyCurrent: boolean;
27
href: string;
28
location: Location;
29
}
30
```
31
32
**Props:**
33
- `to` (string, required) - Destination path (relative or absolute)
34
- `state` (any, optional) - State to pass with navigation
35
- `replace` (boolean, optional) - Replace current history entry instead of pushing
36
- `getProps` (function, optional) - Function to compute additional props based on link state
37
- `innerRef` (React.Ref, optional) - Ref to the underlying anchor element
38
- All standard HTML anchor attributes are supported
39
40
**Usage Examples:**
41
42
```javascript
43
import React from "react";
44
import { Link } from "@reach/router";
45
46
// Basic navigation links
47
const Navigation = () => (
48
<nav>
49
<Link to="/">Home</Link>
50
<Link to="/about">About</Link>
51
<Link to="/contact">Contact</Link>
52
</nav>
53
);
54
55
// Link with state
56
const UserLink = ({ userId }) => (
57
<Link
58
to={`/users/${userId}`}
59
state={{ from: "user-list" }}
60
>
61
View User
62
</Link>
63
);
64
65
// Dynamic styling based on active state
66
const NavLink = ({ to, children, ...props }) => (
67
<Link
68
to={to}
69
getProps={({ isCurrent, isPartiallyCurrent }) => ({
70
className: isCurrent ? "nav-link active" : "nav-link",
71
"aria-current": isCurrent ? "page" : undefined
72
})}
73
{...props}
74
>
75
{children}
76
</Link>
77
);
78
79
// Replace current history entry
80
const ReplaceLink = () => (
81
<Link to="/new-page" replace>
82
Replace Current Page
83
</Link>
84
);
85
86
// Link with custom styling function
87
const StyledLink = ({ to, children }) => (
88
<Link
89
to={to}
90
getProps={({ isCurrent, isPartiallyCurrent, href, location }) => {
91
const baseStyle = { textDecoration: "none", padding: "8px" };
92
const activeStyle = { backgroundColor: "#007bff", color: "white" };
93
const partialStyle = { backgroundColor: "#e9ecef" };
94
95
return {
96
style: {
97
...baseStyle,
98
...(isCurrent ? activeStyle : isPartiallyCurrent ? partialStyle : {})
99
}
100
};
101
}}
102
>
103
{children}
104
</Link>
105
);
106
```
107
108
### Programmatic Navigation
109
110
Navigate function for programmatic navigation outside of components or in response to events.
111
112
```javascript { .api }
113
/**
114
* Global navigation function for programmatic routing
115
* @param to - Destination path or history delta
116
* @param options - Navigation options
117
*/
118
function navigate(
119
to: string | number,
120
options?: {
121
state?: any;
122
replace?: boolean;
123
}
124
): Promise<void>;
125
```
126
127
**Parameters:**
128
- `to` (string | number) - Destination path (string) or history delta (number)
129
- `options.state` (any, optional) - State to associate with the navigation
130
- `options.replace` (boolean, optional) - Replace current history entry
131
132
**Usage Examples:**
133
134
```javascript
135
import { navigate } from "@reach/router";
136
137
// Basic navigation
138
const handleLogin = async () => {
139
const success = await loginUser();
140
if (success) {
141
await navigate("/dashboard");
142
}
143
};
144
145
// Navigation with state
146
const handleUserSelect = (userId) => {
147
navigate(`/users/${userId}`, {
148
state: { selectedFrom: "user-list" }
149
});
150
};
151
152
// Replace current entry
153
const handleRedirect = () => {
154
navigate("/new-location", { replace: true });
155
};
156
157
// History navigation (back/forward)
158
const goBack = () => navigate(-1);
159
const goForward = () => navigate(1);
160
const goBackTwoPages = () => navigate(-2);
161
162
// Navigation in form handlers
163
const handleFormSubmit = async (formData) => {
164
try {
165
await submitForm(formData);
166
navigate("/success");
167
} catch (error) {
168
navigate("/error", { state: { error: error.message } });
169
}
170
};
171
172
// Conditional navigation
173
const handleSave = async (data, shouldRedirect = true) => {
174
await saveData(data);
175
if (shouldRedirect) {
176
navigate("/saved");
177
}
178
};
179
```
180
181
### Navigation Within Components
182
183
Navigation function provided to route components and available through context.
184
185
```javascript { .api }
186
/**
187
* Navigation function provided to route components
188
* This is a scoped version that resolves relative paths
189
*/
190
interface RouteNavigateFunction {
191
(to: string | number, options?: NavigateOptions): Promise<void>;
192
}
193
```
194
195
**Usage Examples:**
196
197
```javascript
198
// In route components, navigate is provided as a prop
199
const UserProfile = ({ userId, navigate, location }) => {
200
const handleEdit = () => {
201
// Relative navigation from current route
202
navigate("edit");
203
};
204
205
const handleDelete = async () => {
206
await deleteUser(userId);
207
// Absolute navigation
208
navigate("/users");
209
};
210
211
const handleCancel = () => {
212
// Go back in history
213
navigate(-1);
214
};
215
216
return (
217
<div>
218
<h1>User: {userId}</h1>
219
<button onClick={handleEdit}>Edit</button>
220
<button onClick={handleDelete}>Delete</button>
221
<button onClick={handleCancel}>Cancel</button>
222
</div>
223
);
224
};
225
226
// Using navigate with state
227
const ProductForm = ({ navigate }) => {
228
const handleSubmit = async (productData) => {
229
const newProduct = await createProduct(productData);
230
navigate(`/products/${newProduct.id}`, {
231
state: { justCreated: true }
232
});
233
};
234
235
return <form onSubmit={handleSubmit}>{/* form content */}</form>;
236
};
237
```
238
239
### Link Active States
240
241
Understanding how Link components determine active states for styling and accessibility.
242
243
```javascript { .api }
244
/**
245
* Link active state detection
246
*/
247
interface LinkActiveState {
248
// True when link path exactly matches current location
249
isCurrent: boolean;
250
// True when current location starts with link path
251
isPartiallyCurrent: boolean;
252
// Resolved href for the link
253
href: string;
254
// Current location object
255
location: Location;
256
}
257
```
258
259
**Usage Examples:**
260
261
```javascript
262
// Understanding active states
263
const ExampleNavigation = () => (
264
<nav>
265
{/* isCurrent: true only when at exactly "/" */}
266
<Link
267
to="/"
268
getProps={({ isCurrent }) => ({
269
className: isCurrent ? "current" : ""
270
})}
271
>
272
Home
273
</Link>
274
275
{/* isPartiallyCurrent: true for "/products", "/products/123", etc. */}
276
<Link
277
to="/products"
278
getProps={({ isPartiallyCurrent }) => ({
279
className: isPartiallyCurrent ? "partial" : ""
280
})}
281
>
282
Products
283
</Link>
284
285
{/* Complex styling based on multiple states */}
286
<Link
287
to="/dashboard"
288
getProps={({ isCurrent, isPartiallyCurrent, location }) => {
289
const isActive = isCurrent || isPartiallyCurrent;
290
return {
291
className: `nav-item ${isActive ? "active" : ""}`,
292
"aria-current": isCurrent ? "page" : undefined,
293
"data-partial": isPartiallyCurrent ? "true" : undefined
294
};
295
}}
296
>
297
Dashboard
298
</Link>
299
</nav>
300
);
301
```