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
Link components and programmatic navigation functions for moving between routes with accessibility features and state management.
Accessible navigation link component with automatic active state detection and focus management.
/**
* Accessible navigation link with active state detection and ref forwarding
* @param props - Link configuration and standard anchor props
* @param ref - Forwarded ref to the anchor element
*/
const Link: React.ForwardRefExoticComponent<{
to: string;
state?: any;
replace?: boolean;
getProps?: (props: LinkGetPropsArgument) => object;
innerRef?: React.Ref<HTMLAnchorElement>;
} & React.AnchorHTMLAttributes<HTMLAnchorElement> & React.RefAttributes<HTMLAnchorElement>>;
interface LinkGetPropsArgument {
isCurrent: boolean;
isPartiallyCurrent: boolean;
href: string;
location: Location;
}Props:
to (string, required) - Destination path (relative or absolute)state (any, optional) - State to pass with navigationreplace (boolean, optional) - Replace current history entry instead of pushinggetProps (function, optional) - Function to compute additional props based on link stateinnerRef (React.Ref, optional) - Ref to the underlying anchor elementUsage Examples:
import React from "react";
import { Link } from "@reach/router";
// Basic navigation links
const Navigation = () => (
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
<Link to="/contact">Contact</Link>
</nav>
);
// Link with state
const UserLink = ({ userId }) => (
<Link
to={`/users/${userId}`}
state={{ from: "user-list" }}
>
View User
</Link>
);
// Dynamic styling based on active state
const NavLink = ({ to, children, ...props }) => (
<Link
to={to}
getProps={({ isCurrent, isPartiallyCurrent }) => ({
className: isCurrent ? "nav-link active" : "nav-link",
"aria-current": isCurrent ? "page" : undefined
})}
{...props}
>
{children}
</Link>
);
// Replace current history entry
const ReplaceLink = () => (
<Link to="/new-page" replace>
Replace Current Page
</Link>
);
// Link with custom styling function
const StyledLink = ({ to, children }) => (
<Link
to={to}
getProps={({ isCurrent, isPartiallyCurrent, href, location }) => {
const baseStyle = { textDecoration: "none", padding: "8px" };
const activeStyle = { backgroundColor: "#007bff", color: "white" };
const partialStyle = { backgroundColor: "#e9ecef" };
return {
style: {
...baseStyle,
...(isCurrent ? activeStyle : isPartiallyCurrent ? partialStyle : {})
}
};
}}
>
{children}
</Link>
);Navigate function for programmatic navigation outside of components or in response to events.
/**
* Global navigation function for programmatic routing
* @param to - Destination path or history delta
* @param options - Navigation options
*/
function navigate(
to: string | number,
options?: {
state?: any;
replace?: boolean;
}
): Promise<void>;Parameters:
to (string | number) - Destination path (string) or history delta (number)options.state (any, optional) - State to associate with the navigationoptions.replace (boolean, optional) - Replace current history entryUsage Examples:
import { navigate } from "@reach/router";
// Basic navigation
const handleLogin = async () => {
const success = await loginUser();
if (success) {
await navigate("/dashboard");
}
};
// Navigation with state
const handleUserSelect = (userId) => {
navigate(`/users/${userId}`, {
state: { selectedFrom: "user-list" }
});
};
// Replace current entry
const handleRedirect = () => {
navigate("/new-location", { replace: true });
};
// History navigation (back/forward)
const goBack = () => navigate(-1);
const goForward = () => navigate(1);
const goBackTwoPages = () => navigate(-2);
// Navigation in form handlers
const handleFormSubmit = async (formData) => {
try {
await submitForm(formData);
navigate("/success");
} catch (error) {
navigate("/error", { state: { error: error.message } });
}
};
// Conditional navigation
const handleSave = async (data, shouldRedirect = true) => {
await saveData(data);
if (shouldRedirect) {
navigate("/saved");
}
};Navigation function provided to route components and available through context.
/**
* Navigation function provided to route components
* This is a scoped version that resolves relative paths
*/
interface RouteNavigateFunction {
(to: string | number, options?: NavigateOptions): Promise<void>;
}Usage Examples:
// In route components, navigate is provided as a prop
const UserProfile = ({ userId, navigate, location }) => {
const handleEdit = () => {
// Relative navigation from current route
navigate("edit");
};
const handleDelete = async () => {
await deleteUser(userId);
// Absolute navigation
navigate("/users");
};
const handleCancel = () => {
// Go back in history
navigate(-1);
};
return (
<div>
<h1>User: {userId}</h1>
<button onClick={handleEdit}>Edit</button>
<button onClick={handleDelete}>Delete</button>
<button onClick={handleCancel}>Cancel</button>
</div>
);
};
// Using navigate with state
const ProductForm = ({ navigate }) => {
const handleSubmit = async (productData) => {
const newProduct = await createProduct(productData);
navigate(`/products/${newProduct.id}`, {
state: { justCreated: true }
});
};
return <form onSubmit={handleSubmit}>{/* form content */}</form>;
};Understanding how Link components determine active states for styling and accessibility.
/**
* Link active state detection
*/
interface LinkActiveState {
// True when link path exactly matches current location
isCurrent: boolean;
// True when current location starts with link path
isPartiallyCurrent: boolean;
// Resolved href for the link
href: string;
// Current location object
location: Location;
}Usage Examples:
// Understanding active states
const ExampleNavigation = () => (
<nav>
{/* isCurrent: true only when at exactly "/" */}
<Link
to="/"
getProps={({ isCurrent }) => ({
className: isCurrent ? "current" : ""
})}
>
Home
</Link>
{/* isPartiallyCurrent: true for "/products", "/products/123", etc. */}
<Link
to="/products"
getProps={({ isPartiallyCurrent }) => ({
className: isPartiallyCurrent ? "partial" : ""
})}
>
Products
</Link>
{/* Complex styling based on multiple states */}
<Link
to="/dashboard"
getProps={({ isCurrent, isPartiallyCurrent, location }) => {
const isActive = isCurrent || isPartiallyCurrent;
return {
className: `nav-item ${isActive ? "active" : ""}`,
"aria-current": isCurrent ? "page" : undefined,
"data-partial": isPartiallyCurrent ? "true" : undefined
};
}}
>
Dashboard
</Link>
</nav>
);Install with Tessl CLI
npx tessl i tessl/npm-reach--router