Next generation React routing library with accessible navigation and focus management.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Location providers and consumer components for accessing current location state and navigation functions in React components.
React context provider that manages location state and navigation functionality for the application.
/**
* Context provider for location state and navigation functionality
* @param props - Provider configuration
*/
function LocationProvider(props: {
history?: History;
children: React.ReactNode | ((context: LocationContext) => React.ReactNode);
}): React.ReactElement;
interface LocationContext {
location: Location;
navigate: (to: string | number, options?: NavigateOptions) => Promise<void>;
}
interface History {
location: Location;
transitioning: boolean;
listen(listener: (event: HistoryEvent) => void): () => void;
navigate(to: string | number, options?: NavigateOptions): Promise<void>;
_onTransitionComplete(): void;
}
interface HistoryEvent {
location: Location;
action: "PUSH" | "POP";
}Props:
history (History, optional) - Custom history instance (defaults to globalHistory)children - React nodes or render function receiving contextUsage Examples:
import React from "react";
import { LocationProvider, createHistory, createMemorySource } from "@reach/router";
// Basic usage with default history
const App = () => (
<LocationProvider>
<AppContent />
</LocationProvider>
);
// Custom history for testing
const TestApp = () => {
const testHistory = createHistory(createMemorySource("/test-path"));
return (
<LocationProvider history={testHistory}>
<AppContent />
</LocationProvider>
);
};
// Render prop pattern
const App = () => (
<LocationProvider>
{({ location, navigate }) => (
<div>
<p>Current path: {location.pathname}</p>
<button onClick={() => navigate("/about")}>Go to About</button>
<AppContent />
</div>
)}
</LocationProvider>
);
// Multiple providers for different app sections
const MultiProviderApp = () => (
<div>
<LocationProvider history={mainHistory}>
<MainApp />
</LocationProvider>
<LocationProvider history={adminHistory}>
<AdminPanel />
</LocationProvider>
</div>
);Component for consuming location context without using hooks (useful for class components or render props).
/**
* Consumer component for accessing location context
* @param props - Consumer configuration
*/
function Location(props: {
children: (context: LocationContext) => React.ReactNode;
}): React.ReactElement;Usage Examples:
import React from "react";
import { Location } from "@reach/router";
// Basic render prop usage
const LocationInfo = () => (
<Location>
{({ location, navigate }) => (
<div>
<h2>Current Location</h2>
<p>Path: {location.pathname}</p>
<p>Search: {location.search}</p>
<button onClick={() => navigate("/")}>Home</button>
</div>
)}
</Location>
);
// Class component usage
class ClassComponent extends React.Component {
render() {
return (
<Location>
{({ location, navigate }) => (
<div>
<p>Location in class: {location.pathname}</p>
<button onClick={() => navigate("/next")}>
Navigate
</button>
</div>
)}
</Location>
);
}
}
// Conditional rendering based on location
const ConditionalContent = () => (
<Location>
{({ location }) => (
<>
{location.pathname === "/" && <HomePage />}
{location.pathname.startsWith("/admin") && <AdminWarning />}
{location.search.includes("debug=true") && <DebugPanel />}
</>
)}
</Location>
);
// Navigation controls
const NavigationControls = () => (
<Location>
{({ location, navigate }) => (
<div className="nav-controls">
<button
onClick={() => navigate(-1)}
disabled={!window.history.state}
>
Back
</button>
<span>Current: {location.pathname}</span>
<button onClick={() => navigate("/")}>
Home
</button>
</div>
)}
</Location>
);Common patterns for integrating location context with other React patterns.
Usage Examples:
// Higher-order component pattern
const withLocation = (Component) => {
return (props) => (
<Location>
{(locationProps) => (
<Component {...props} {...locationProps} />
)}
</Location>
);
};
const EnhancedComponent = withLocation(({ location, navigate, ...props }) => (
<div>
<p>Path: {location.pathname}</p>
<MyComponent {...props} />
</div>
));
// Custom hook using context (alternative to useLocation)
const useLocationContext = () => {
const [context, setContext] = React.useState(null);
return (
<Location>
{(locationContext) => {
if (!context) setContext(locationContext);
return null;
}}
</Location>
);
};
// Context provider wrapper
const LocationContextProvider = ({ children }) => {
return (
<LocationProvider>
<Location>
{(locationContext) => (
<MyCustomContext.Provider value={locationContext}>
{children}
</MyCustomContext.Provider>
)}
</Location>
</LocationProvider>
);
};
// Multiple context consumers
const MultiContextComponent = () => (
<UserContext.Consumer>
{(user) => (
<ThemeContext.Consumer>
{(theme) => (
<Location>
{({ location, navigate }) => (
<div className={theme.className}>
<p>User: {user.name}</p>
<p>Path: {location.pathname}</p>
<button onClick={() => navigate("/profile")}>
Profile
</button>
</div>
)}
</Location>
)}
</ThemeContext.Consumer>
)}
</UserContext.Consumer>
);Understanding how location context manages state and updates.
/**
* Location context state management
*/
interface LocationContextBehavior {
// Context updates when:
// - Browser navigation (back/forward)
// - Programmatic navigation via navigate()
// - URL changes from external sources
// Context provides:
// - Current location object
// - Navigation function
// - Automatic re-rendering on location changes
}Usage Examples:
// Listening to location changes
const LocationLogger = () => {
const [history, setHistory] = React.useState([]);
return (
<Location>
{({ location }) => {
React.useEffect(() => {
setHistory(prev => [
...prev,
{ pathname: location.pathname, timestamp: Date.now() }
]);
}, [location.pathname]);
return (
<div>
<h3>Navigation History</h3>
{history.map((entry, index) => (
<div key={index}>
{entry.pathname} at {new Date(entry.timestamp).toLocaleTimeString()}
</div>
))}
</div>
);
}}
</Location>
);
};
// Persisting location state
const LocationPersistence = () => (
<Location>
{({ location }) => {
React.useEffect(() => {
localStorage.setItem("lastLocation", location.pathname);
}, [location.pathname]);
return <div>Location saved to localStorage</div>;
}}
</Location>
);
// Conditional effects based on location
const LocationEffects = () => (
<Location>
{({ location }) => {
React.useEffect(() => {
// Track page views
analytics.track("pageview", { path: location.pathname });
}, [location.pathname]);
React.useEffect(() => {
// Update document title
const titles = {
"/": "Home",
"/about": "About Us",
"/contact": "Contact"
};
document.title = titles[location.pathname] || "Page";
}, [location.pathname]);
return null;
}}
</Location>
);
// Error boundaries with location context
class LocationErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false, errorLocation: null };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
console.error("Error at location:", this.state.errorLocation);
}
render() {
if (this.state.hasError) {
return (
<Location>
{({ location, navigate }) => (
<div>
<h2>Something went wrong at {location.pathname}</h2>
<button onClick={() => navigate("/")}>Go Home</button>
</div>
)}
</Location>
);
}
return (
<Location>
{({ location }) => {
this.state.errorLocation = location.pathname;
return this.props.children;
}}
</Location>
);
}
}Install with Tessl CLI
npx tessl i tessl/npm-reach--router