Link
On this page

<Link>

This is the web version of <Link>. For the React Native version, go here.

Type declaration
declare function Link(props: LinkProps): React.ReactElement;

interface LinkProps
  extends Omit<
    React.AnchorHTMLAttributes<HTMLAnchorElement>,
    "href"
  > {
  replace?: boolean;
  state?: any;
  to: To;
  reloadDocument?: boolean;
  preventScrollReset?: boolean;
  relative?: "route" | "path";
}

type To = string | Partial<Path>;

interface Path {
  pathname: string;
  search: string;
  hash: string;
}

A <Link> is an element that lets the user navigate to another page by clicking or tapping on it. In react-router-dom, a <Link> renders an accessible <a> element with a real href that points to the resource it's linking to. This means that things like right-clicking a <Link> work as you'd expect. You can use <Link reloadDocument> to skip client side routing and let the browser handle the transition normally (as if it were an <a href>).

import * as React from "react";
import { Link } from "react-router-dom";

function UsersIndexPage({ users }) {
  return (
    <div>
      <h1>Users</h1>
      <ul>
        {users.map((user) => (
          <li key={user.id}>
            <Link to={user.id}>{user.name}</Link>
          </li>
        ))}
      </ul>
    </div>
  );
}

A relative <Link to> value (that does not begin with /) resolves relative to the parent route, which means that it builds upon the URL path that was matched by the route that rendered that <Link>. It may contain .. to link to routes further up the hierarchy. In these cases, .. works exactly like the command-line cd function; each .. removes one segment of the parent path.

<Link to> with a .. behaves differently from a normal <a href> when the current URL ends with /. <Link to> ignores the trailing slash, and removes one URL segment for each ... But an <a href> value handles .. differently when the current URL ends with / vs when it does not.

relative

By default, links are relative to the route hierarchy (relative="route"), so .. will go up one Route level. Occasionally, you may find that you have matching URL patterns that do not make sense to be nested, and you'd prefer to use relative path routing. You can opt into this behavior with relative="path":

// Contact and EditContact do not share additional UI layout
<Route path="/" element={<Layout />}>
  <Route path="contacts/:id" element={<Contact />} />
  <Route
    path="contacts/:id/edit"
    element={<EditContact />}
  />
</Route>;

function EditContact() {
  // Since Contact is not a parent of EditContact we need to go up one level
  // in the path, instead of one level in the Route hierarchy
  return (
    <Link to=".." relative="path">
      Cancel
    </Link>
  );
}

preventScrollReset

If you are using <ScrollRestoration>, this lets you prevent the scroll position from being reset to the top of the window when the link is clicked.

<Link to="?tab=one" preventScrollReset={true} />

This does not prevent the scroll position from being restored when the user comes back to the location with the back/forward buttons, it just prevents the reset when the user clicks the link.

An example when you might want this behavior is a list of tabs that manipulate the url search params that aren't at the top of the page. You wouldn't want the scroll position to jump up to the top because it might scroll the toggled content out of the viewport!

      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
      β”‚                         β”œβ”€β”€β”
      β”‚                         β”‚  β”‚
      β”‚                         β”‚  β”‚ scrolled
      β”‚                         β”‚  β”‚ out of view
      β”‚                         β”‚  β”‚
      β”‚                         β”‚ β—„β”˜
    β”Œβ”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”
    β”‚                             β”œβ”€β”
    β”‚                             β”‚ β”‚ viewport
    β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚ β”‚
    β”‚   β”‚  tab   tab   tab    β”‚   β”‚ β”‚
    β”‚   β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€   β”‚ β”‚
    β”‚   β”‚                     β”‚   β”‚ β”‚
    β”‚   β”‚                     β”‚   β”‚ β”‚
    β”‚   β”‚ content             β”‚   β”‚ β”‚
    β”‚   β”‚                     β”‚   β”‚ β”‚
    β”‚   β”‚                     β”‚   β”‚ β”‚
    β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚ β”‚
    β”‚                             β”‚β—„β”˜
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

replace

The replace property can be used if you'd like to replace the current entry in the history stack via history.replaceState instead of the default usage of history.pushState.

state

The state property can be used to set a stateful value for the new location which is stored inside history state. This value can subsequently be accessed via useLocation().

<Link to="new-path" state={{ some: "value" }} />

You can access this state value while on the "new-path" route:

let { state } = useLocation();

reloadDocument

The reloadDocument property can be used to skip client side routing and let the browser handle the transition normally (as if it were an <a href>).

Docs and examples CC 4.0