0
# Location and Context
1
2
Location providers and consumer components for accessing current location state and navigation functions in React components.
3
4
## Capabilities
5
6
### LocationProvider Component
7
8
React context provider that manages location state and navigation functionality for the application.
9
10
```javascript { .api }
11
/**
12
* Context provider for location state and navigation functionality
13
* @param props - Provider configuration
14
*/
15
function LocationProvider(props: {
16
history?: History;
17
children: React.ReactNode | ((context: LocationContext) => React.ReactNode);
18
}): React.ReactElement;
19
20
interface LocationContext {
21
location: Location;
22
navigate: (to: string | number, options?: NavigateOptions) => Promise<void>;
23
}
24
25
interface History {
26
location: Location;
27
transitioning: boolean;
28
listen(listener: (event: HistoryEvent) => void): () => void;
29
navigate(to: string | number, options?: NavigateOptions): Promise<void>;
30
_onTransitionComplete(): void;
31
}
32
33
interface HistoryEvent {
34
location: Location;
35
action: "PUSH" | "POP";
36
}
37
```
38
39
**Props:**
40
- `history` (History, optional) - Custom history instance (defaults to globalHistory)
41
- `children` - React nodes or render function receiving context
42
43
**Usage Examples:**
44
45
```javascript
46
import React from "react";
47
import { LocationProvider, createHistory, createMemorySource } from "@reach/router";
48
49
// Basic usage with default history
50
const App = () => (
51
<LocationProvider>
52
<AppContent />
53
</LocationProvider>
54
);
55
56
// Custom history for testing
57
const TestApp = () => {
58
const testHistory = createHistory(createMemorySource("/test-path"));
59
60
return (
61
<LocationProvider history={testHistory}>
62
<AppContent />
63
</LocationProvider>
64
);
65
};
66
67
// Render prop pattern
68
const App = () => (
69
<LocationProvider>
70
{({ location, navigate }) => (
71
<div>
72
<p>Current path: {location.pathname}</p>
73
<button onClick={() => navigate("/about")}>Go to About</button>
74
<AppContent />
75
</div>
76
)}
77
</LocationProvider>
78
);
79
80
// Multiple providers for different app sections
81
const MultiProviderApp = () => (
82
<div>
83
<LocationProvider history={mainHistory}>
84
<MainApp />
85
</LocationProvider>
86
87
<LocationProvider history={adminHistory}>
88
<AdminPanel />
89
</LocationProvider>
90
</div>
91
);
92
```
93
94
### Location Consumer Component
95
96
Component for consuming location context without using hooks (useful for class components or render props).
97
98
```javascript { .api }
99
/**
100
* Consumer component for accessing location context
101
* @param props - Consumer configuration
102
*/
103
function Location(props: {
104
children: (context: LocationContext) => React.ReactNode;
105
}): React.ReactElement;
106
```
107
108
**Usage Examples:**
109
110
```javascript
111
import React from "react";
112
import { Location } from "@reach/router";
113
114
// Basic render prop usage
115
const LocationInfo = () => (
116
<Location>
117
{({ location, navigate }) => (
118
<div>
119
<h2>Current Location</h2>
120
<p>Path: {location.pathname}</p>
121
<p>Search: {location.search}</p>
122
<button onClick={() => navigate("/")}>Home</button>
123
</div>
124
)}
125
</Location>
126
);
127
128
// Class component usage
129
class ClassComponent extends React.Component {
130
render() {
131
return (
132
<Location>
133
{({ location, navigate }) => (
134
<div>
135
<p>Location in class: {location.pathname}</p>
136
<button onClick={() => navigate("/next")}>
137
Navigate
138
</button>
139
</div>
140
)}
141
</Location>
142
);
143
}
144
}
145
146
// Conditional rendering based on location
147
const ConditionalContent = () => (
148
<Location>
149
{({ location }) => (
150
<>
151
{location.pathname === "/" && <HomePage />}
152
{location.pathname.startsWith("/admin") && <AdminWarning />}
153
{location.search.includes("debug=true") && <DebugPanel />}
154
</>
155
)}
156
</Location>
157
);
158
159
// Navigation controls
160
const NavigationControls = () => (
161
<Location>
162
{({ location, navigate }) => (
163
<div className="nav-controls">
164
<button
165
onClick={() => navigate(-1)}
166
disabled={!window.history.state}
167
>
168
Back
169
</button>
170
<span>Current: {location.pathname}</span>
171
<button onClick={() => navigate("/")}>
172
Home
173
</button>
174
</div>
175
)}
176
</Location>
177
);
178
```
179
180
### Context Integration Patterns
181
182
Common patterns for integrating location context with other React patterns.
183
184
**Usage Examples:**
185
186
```javascript
187
// Higher-order component pattern
188
const withLocation = (Component) => {
189
return (props) => (
190
<Location>
191
{(locationProps) => (
192
<Component {...props} {...locationProps} />
193
)}
194
</Location>
195
);
196
};
197
198
const EnhancedComponent = withLocation(({ location, navigate, ...props }) => (
199
<div>
200
<p>Path: {location.pathname}</p>
201
<MyComponent {...props} />
202
</div>
203
));
204
205
// Custom hook using context (alternative to useLocation)
206
const useLocationContext = () => {
207
const [context, setContext] = React.useState(null);
208
209
return (
210
<Location>
211
{(locationContext) => {
212
if (!context) setContext(locationContext);
213
return null;
214
}}
215
</Location>
216
);
217
};
218
219
// Context provider wrapper
220
const LocationContextProvider = ({ children }) => {
221
return (
222
<LocationProvider>
223
<Location>
224
{(locationContext) => (
225
<MyCustomContext.Provider value={locationContext}>
226
{children}
227
</MyCustomContext.Provider>
228
)}
229
</Location>
230
</LocationProvider>
231
);
232
};
233
234
// Multiple context consumers
235
const MultiContextComponent = () => (
236
<UserContext.Consumer>
237
{(user) => (
238
<ThemeContext.Consumer>
239
{(theme) => (
240
<Location>
241
{({ location, navigate }) => (
242
<div className={theme.className}>
243
<p>User: {user.name}</p>
244
<p>Path: {location.pathname}</p>
245
<button onClick={() => navigate("/profile")}>
246
Profile
247
</button>
248
</div>
249
)}
250
</Location>
251
)}
252
</ThemeContext.Consumer>
253
)}
254
</UserContext.Consumer>
255
);
256
```
257
258
### Location Context State Management
259
260
Understanding how location context manages state and updates.
261
262
```javascript { .api }
263
/**
264
* Location context state management
265
*/
266
interface LocationContextBehavior {
267
// Context updates when:
268
// - Browser navigation (back/forward)
269
// - Programmatic navigation via navigate()
270
// - URL changes from external sources
271
272
// Context provides:
273
// - Current location object
274
// - Navigation function
275
// - Automatic re-rendering on location changes
276
}
277
```
278
279
**Usage Examples:**
280
281
```javascript
282
// Listening to location changes
283
const LocationLogger = () => {
284
const [history, setHistory] = React.useState([]);
285
286
return (
287
<Location>
288
{({ location }) => {
289
React.useEffect(() => {
290
setHistory(prev => [
291
...prev,
292
{ pathname: location.pathname, timestamp: Date.now() }
293
]);
294
}, [location.pathname]);
295
296
return (
297
<div>
298
<h3>Navigation History</h3>
299
{history.map((entry, index) => (
300
<div key={index}>
301
{entry.pathname} at {new Date(entry.timestamp).toLocaleTimeString()}
302
</div>
303
))}
304
</div>
305
);
306
}}
307
</Location>
308
);
309
};
310
311
// Persisting location state
312
const LocationPersistence = () => (
313
<Location>
314
{({ location }) => {
315
React.useEffect(() => {
316
localStorage.setItem("lastLocation", location.pathname);
317
}, [location.pathname]);
318
319
return <div>Location saved to localStorage</div>;
320
}}
321
</Location>
322
);
323
324
// Conditional effects based on location
325
const LocationEffects = () => (
326
<Location>
327
{({ location }) => {
328
React.useEffect(() => {
329
// Track page views
330
analytics.track("pageview", { path: location.pathname });
331
}, [location.pathname]);
332
333
React.useEffect(() => {
334
// Update document title
335
const titles = {
336
"/": "Home",
337
"/about": "About Us",
338
"/contact": "Contact"
339
};
340
document.title = titles[location.pathname] || "Page";
341
}, [location.pathname]);
342
343
return null;
344
}}
345
</Location>
346
);
347
348
// Error boundaries with location context
349
class LocationErrorBoundary extends React.Component {
350
constructor(props) {
351
super(props);
352
this.state = { hasError: false, errorLocation: null };
353
}
354
355
static getDerivedStateFromError(error) {
356
return { hasError: true };
357
}
358
359
componentDidCatch(error, errorInfo) {
360
console.error("Error at location:", this.state.errorLocation);
361
}
362
363
render() {
364
if (this.state.hasError) {
365
return (
366
<Location>
367
{({ location, navigate }) => (
368
<div>
369
<h2>Something went wrong at {location.pathname}</h2>
370
<button onClick={() => navigate("/")}>Go Home</button>
371
</div>
372
)}
373
</Location>
374
);
375
}
376
377
return (
378
<Location>
379
{({ location }) => {
380
this.state.errorLocation = location.pathname;
381
return this.props.children;
382
}}
383
</Location>
384
);
385
}
386
}
387
```