0
# React Hooks
1
2
Modern React hooks for accessing routing state and navigation functions in functional components.
3
4
## Capabilities
5
6
### useLocation Hook
7
8
Hook to access the current location object containing path, search, hash, and state information.
9
10
```javascript { .api }
11
/**
12
* Hook to access current location object
13
* @returns Current location with pathname, search, hash, state, etc.
14
* @throws Error if used outside LocationProvider
15
*/
16
function useLocation(): Location;
17
18
interface Location {
19
pathname: string; // URI encoded/decoded
20
search: string;
21
hash: string;
22
href?: string; // Optional in non-browser environments
23
origin?: string; // Optional in non-browser environments
24
protocol?: string; // Optional in non-browser environments
25
host?: string; // Optional in non-browser environments
26
hostname?: string; // Optional in non-browser environments
27
port?: string; // Optional in non-browser environments
28
state: any;
29
key: string; // Defaults to "initial"
30
}
31
```
32
33
**Usage Examples:**
34
35
```javascript
36
import React from "react";
37
import { useLocation } from "@reach/router";
38
39
// Basic location access
40
const LocationDisplay = () => {
41
const location = useLocation();
42
43
return (
44
<div>
45
<p>Current path: {location.pathname}</p>
46
<p>Query string: {location.search}</p>
47
<p>Hash: {location.hash}</p>
48
</div>
49
);
50
};
51
52
// Conditional rendering based on location
53
const Header = () => {
54
const location = useLocation();
55
const isHomePage = location.pathname === "/";
56
57
return (
58
<header className={isHomePage ? "home-header" : "page-header"}>
59
{isHomePage ? <HeroSection /> : <PageTitle />}
60
</header>
61
);
62
};
63
64
// Accessing navigation state
65
const WelcomeMessage = () => {
66
const location = useLocation();
67
const { justLoggedIn } = location.state || {};
68
69
return (
70
<div>
71
{justLoggedIn && <p>Welcome back! You've successfully logged in.</p>}
72
</div>
73
);
74
};
75
76
// URL parameter parsing
77
const SearchResults = () => {
78
const location = useLocation();
79
const queryParams = new URLSearchParams(location.search);
80
const query = queryParams.get("q");
81
const page = parseInt(queryParams.get("page") || "1");
82
83
return (
84
<div>
85
<h1>Search Results for: {query}</h1>
86
<p>Page {page}</p>
87
</div>
88
);
89
};
90
```
91
92
### useNavigate Hook
93
94
Hook to access the navigation function for programmatic routing within components.
95
96
```javascript { .api }
97
/**
98
* Hook to access navigation function
99
* @returns Navigation function for programmatic routing
100
* @throws Error if used outside LocationProvider
101
*/
102
function useNavigate(): NavigateFunction;
103
104
interface NavigateFunction {
105
(to: string | number, options?: NavigateOptions): Promise<void>;
106
}
107
108
interface NavigateOptions {
109
state?: any;
110
replace?: boolean;
111
}
112
```
113
114
**Usage Examples:**
115
116
```javascript
117
import React from "react";
118
import { useNavigate } from "@reach/router";
119
120
// Basic programmatic navigation
121
const LoginForm = () => {
122
const navigate = useNavigate();
123
124
const handleSubmit = async (formData) => {
125
const success = await login(formData);
126
if (success) {
127
navigate("/dashboard");
128
}
129
};
130
131
return <form onSubmit={handleSubmit}>{/* form content */}</form>;
132
};
133
134
// Navigation with state
135
const ProductCreator = () => {
136
const navigate = useNavigate();
137
138
const handleCreate = async (productData) => {
139
const newProduct = await createProduct(productData);
140
navigate(`/products/${newProduct.id}`, {
141
state: { justCreated: true, product: newProduct }
142
});
143
};
144
145
return <ProductForm onSubmit={handleCreate} />;
146
};
147
148
// History navigation
149
const NavigationControls = () => {
150
const navigate = useNavigate();
151
152
return (
153
<div>
154
<button onClick={() => navigate(-1)}>Back</button>
155
<button onClick={() => navigate(1)}>Forward</button>
156
<button onClick={() => navigate("/")}>Home</button>
157
</div>
158
);
159
};
160
161
// Conditional navigation with replace
162
const RedirectHandler = ({ shouldRedirect, redirectTo }) => {
163
const navigate = useNavigate();
164
165
React.useEffect(() => {
166
if (shouldRedirect) {
167
navigate(redirectTo, { replace: true });
168
}
169
}, [shouldRedirect, redirectTo, navigate]);
170
171
return null;
172
};
173
```
174
175
### useParams Hook
176
177
Hook to access route parameters from the current matched route.
178
179
```javascript { .api }
180
/**
181
* Hook to access route parameters from current matched route
182
* Matches parameters against the current base path context
183
* @returns Object with route parameters or null if no match
184
* @throws Error if used outside Router
185
*/
186
function useParams(): Record<string, string | string[]> | null;
187
```
188
189
**Usage Examples:**
190
191
```javascript
192
import React from "react";
193
import { useParams } from "@reach/router";
194
195
// Basic parameter access
196
const UserProfile = () => {
197
const params = useParams();
198
const { userId } = params || {};
199
200
if (!userId) {
201
return <div>No user specified</div>;
202
}
203
204
return <div>User ID: {userId}</div>;
205
};
206
207
// Multiple parameters
208
const BlogPost = () => {
209
const params = useParams();
210
const { category, postId } = params || {};
211
212
return (
213
<article>
214
<p>Category: {category}</p>
215
<p>Post ID: {postId}</p>
216
</article>
217
);
218
};
219
220
// Parameter validation and effects
221
const ProductDetails = () => {
222
const params = useParams();
223
const { productId } = params || {};
224
const [product, setProduct] = React.useState(null);
225
const [loading, setLoading] = React.useState(true);
226
227
React.useEffect(() => {
228
if (productId) {
229
setLoading(true);
230
fetchProduct(productId)
231
.then(setProduct)
232
.finally(() => setLoading(false));
233
}
234
}, [productId]);
235
236
if (!productId) {
237
return <div>Product not found</div>;
238
}
239
240
if (loading) {
241
return <div>Loading...</div>;
242
}
243
244
return <div>Product: {product?.name}</div>;
245
};
246
247
// Using with wildcard parameters
248
const FileViewer = () => {
249
const params = useParams();
250
const filepath = params["*"]; // or params.filepath if named wildcard
251
252
return (
253
<div>
254
<h1>File Viewer</h1>
255
<p>File path: {filepath}</p>
256
</div>
257
);
258
};
259
```
260
261
### useMatch Hook
262
263
Hook to check if a specific path matches the current location and get match details.
264
265
```javascript { .api }
266
/**
267
* Hook to check if a path matches current location
268
* @param path - Path pattern to match against
269
* @returns Match result with params and uri, or null if no match
270
* @throws Error if used outside Router or if path is not provided
271
*/
272
function useMatch(path: string): MatchResult | null;
273
274
interface MatchResult {
275
uri: string; // Always normalized with leading slash
276
path: string;
277
[paramName: string]: string | string[]; // Can contain arrays for splat routes
278
}
279
```
280
281
**Usage Examples:**
282
283
```javascript
284
import React from "react";
285
import { useMatch } from "@reach/router";
286
287
// Basic path matching
288
const ConditionalComponent = () => {
289
const match = useMatch("/admin/*");
290
291
if (match) {
292
return <AdminToolbar />;
293
}
294
295
return null;
296
};
297
298
// Match with parameters
299
const UserContextProvider = ({ children }) => {
300
const userMatch = useMatch("/users/:userId/*");
301
const userId = userMatch?.userId;
302
303
return (
304
<UserContext.Provider value={{ userId }}>
305
{children}
306
</UserContext.Provider>
307
);
308
};
309
310
// Multiple matches for complex logic
311
const PageLayout = ({ children }) => {
312
const dashboardMatch = useMatch("/dashboard/*");
313
const adminMatch = useMatch("/admin/*");
314
const publicMatch = useMatch("/public/*");
315
316
let layoutClass = "default-layout";
317
if (dashboardMatch) layoutClass = "dashboard-layout";
318
else if (adminMatch) layoutClass = "admin-layout";
319
else if (publicMatch) layoutClass = "public-layout";
320
321
return (
322
<div className={layoutClass}>
323
{dashboardMatch && <DashboardSidebar />}
324
{adminMatch && <AdminHeader />}
325
<main>{children}</main>
326
</div>
327
);
328
};
329
330
// Dynamic styling based on match
331
const NavigationItem = ({ path, children }) => {
332
const match = useMatch(path);
333
334
return (
335
<li className={match ? "nav-item active" : "nav-item"}>
336
{children}
337
</li>
338
);
339
};
340
341
// Accessing match details
342
const BreadcrumbTrail = () => {
343
const productMatch = useMatch("/products/:productId");
344
const categoryMatch = useMatch("/categories/:categoryId");
345
346
const breadcrumbs = [];
347
348
if (categoryMatch) {
349
breadcrumbs.push({
350
label: `Category ${categoryMatch.categoryId}`,
351
path: `/categories/${categoryMatch.categoryId}`
352
});
353
}
354
355
if (productMatch) {
356
breadcrumbs.push({
357
label: `Product ${productMatch.productId}`,
358
path: `/products/${productMatch.productId}`
359
});
360
}
361
362
return (
363
<nav>
364
{breadcrumbs.map((crumb, index) => (
365
<span key={index}>
366
<Link to={crumb.path}>{crumb.label}</Link>
367
{index < breadcrumbs.length - 1 && " > "}
368
</span>
369
))}
370
</nav>
371
);
372
};
373
```
374
375
### Hook Usage Requirements
376
377
All hooks must be used within the appropriate context providers.
378
379
```javascript { .api }
380
/**
381
* Hook usage requirements:
382
* - useLocation and useNavigate require LocationProvider or Router
383
* - useParams and useMatch require Router
384
* - All hooks follow standard React hooks rules
385
*/
386
```
387
388
**Usage Examples:**
389
390
```javascript
391
// Correct usage - hooks inside providers
392
const App = () => (
393
<Router>
394
<UserProfile path="/users/:userId" />
395
</Router>
396
);
397
398
const UserProfile = () => {
399
const params = useParams(); // ✓ Inside Router
400
const location = useLocation(); // ✓ Inside Router (which provides LocationProvider)
401
const navigate = useNavigate(); // ✓ Inside Router
402
const match = useMatch("/users/:userId/settings"); // ✓ Inside Router
403
404
return <div>User: {params.userId}</div>;
405
};
406
407
// Error handling for missing context
408
const SafeComponent = () => {
409
try {
410
const location = useLocation();
411
return <div>Path: {location.pathname}</div>;
412
} catch (error) {
413
return <div>Component must be used within a Router</div>;
414
}
415
};
416
417
// Custom hook combining multiple routing hooks
418
const useRouteInfo = () => {
419
const location = useLocation();
420
const params = useParams();
421
const navigate = useNavigate();
422
423
return {
424
location,
425
params,
426
navigate,
427
isHomePage: location.pathname === "/",
428
queryParams: new URLSearchParams(location.search)
429
};
430
};
431
```