React Router β€” Go back using <Link>
Asked Answered
C

7

13

In React Router v6, how can I go back to the previous page using <Link> instead of useNavigate().

// Instead of this...
<button onClick={() => navigate(-1)}>
// ...it needs to be this:
const previousPage = ???

<Link to={previousPage}>Go back</Link>

I don't know what URL to pass to the Link.

Why is it important: Changing it to <Link> would allow me to use <a href="xxxx"> instead of a <button>, which is the most accessible way of creating links between pages. (More about button vs links). For example, it allows users to:

  • right-click and open the page in a new tab.
  • when it's the first opened page, the "back" does not work at all, while the link works always.

Update: I've created a codesandbox to help you find the solution.

Update 2: Based on the answers and some research, I created a GitHub issue to react-router

Update 3: I've added my own answer below.

Caritacaritas answered 19/6, 2022 at 10:17 Comment(0)
C
3

As far as I know, it's impossible to have a fully accessible "Go Back" link with:

  <Link to={-1}>Go back</Link>
  // or
  <button onClick={() => navigate(-1)}>Go back</button>

It's not fully accessible for 2 reasons:

  1. Click does not work when you come directly from the first page (on mount).
  2. Right-click (open in a new tab) never works.

For 1) I found a workaround:

const router = useRouter(); // next/router

function handleGoBack() {
   // πŸ’‘ Verify if previous page exists before using router.back
    const hasPreviousPage = window.history.length > 1;

    if (hasPreviousPage) {
      router.back();
    } else {
      // fallback to a meaningful route.
      router.push("/");
    }
}

<button onClick={handleGoBack}>
  Go back
</button>

For 2) I didn't find any solution. My recommendation would be to avoid "go back" links using -1 whenever you can, in favor of using <Link> with a real URL to the possible previous page.

Caritacaritas answered 19/5, 2023 at 16:34 Comment(1)
Workaround 2 could be: use a <button onClick={(e) => { history.back(); }} />Go Back</button> – Nannettenanni
A
10

It's not a bug in react-router-dom@6 and not really anything a Link is meant to do, i.e. it's just an anchor tag under the hood, and links to a path as a declarative navigation action. This is fundamentally different than an imperative action like history.go(1) or history.back() (i.e. history.go(-1)) where you are imperatively saying to navigate forward/backward through the history stack.

In react-router-dom@6, however, you can navigate relative to the current path. ".." will navigate "back" one path segment for any Route components rendered within the current Routes component. I.E. from "/destiny" back to "/" with the same Routes component.

Example:

import { Link } from 'react-router-dom';

export default function Destiny() {
  return (
    <div>
      <h1>Destiny Page</h1>
      <Link to={'..'}>Go back</Link>
      <br />
      <Link to="/">Go Home ("/")</Link>
    </div>
  );
}

Note that this isn't the equivalent of navigate(-1) as it isn't transitioning through the history stack, so it's not a true back navigation. If you want to do a true back navigation then you'll want to add an onClick handler to the Link and prevent the default event action and handle issuing an imperative back navigation.

Example:

import { useNavigate, Link } from 'react-router-dom';

export default function Destiny() {
  const navigate = useNavigate();

  return (
    <div>
      <h1>Destiny Page</h1>
      <Link
        to={'..'}
        onClick={(e) => {
          e.preventDefault();
          navigate(-1);
        }}
      >
        Go back (-1)
      </Link>
      <br />
      <Link to="/">Go Home ("/")</Link>
    </div>
  );
}

Edit react-router-go-back-using-link

Amora answered 20/6, 2022 at 18:52 Comment(4)
Yes, to={'..'} is a hack. The solution with onClick is not great because if the user opens the link on a new page (eg right click on it), it won't go to the same route as navigate(-1). I believe the solution is using vanilla JS to get the latest visited page and set it as href. I'll try to accomplish that later tomorrow. – Caritacaritas
@Caritacaritas Sorry, I don't follow your comment regarding the onClick handler not working, it uses the same navigate(-1) that would be used elsewhere. I saw your comment in github, can you clarify your comment about not being accessible? I can't quite wrap my head around the comment about opening a new page and getting the code to not go to the intended target, so perhaps I'm not understanding what you are specifically referring to. – Amora
Here's the Loom video I made showcase the problem. Try homepage > middle > destiny. Click on "go back(-1)" with a right click (or copy the link). It will to go to the "homepage" instead of the "middle" page. – Caritacaritas
@Caritacaritas I see, I was suspecting it was an issue with the way ".." resolved to a target URL. Like I said, it's not technically a back navigation, it navigates a path segment back/up. There's not really any anchor-tag/link way to issue a back navigation other than providing an onClick handler and overriding the default link behavior. What you could try doing is maintaining your own history stack in app state and provide this as a target path for any link you want to use to navigate to the previous location. Note however that this still isn't a back navigation, it'll be a PUSH, not a POP. – Amora
F
3

<Link to={-1}>Go Back</Link> will work.

Freon answered 19/6, 2022 at 10:25 Comment(7)
Hum, in this codesandbox, it didn't work. codesandbox.io/s/a11y-into-js-forked-7oq2vq?file=/src/App.js – Caritacaritas
Update: I think we found a bug with React Router β€” it does not work on the first attempt, but it does if we go to another page first (eg /middle). However, the go back link is always "/destiny", even when it works. I will report a bug on react router repo. – Caritacaritas
I just tested on that sandbox. Seems to be working. Here's my fork of it. I refactored some of the routing code to make it cleaner. codesandbox.io/s/a11y-into-js-forked-hx2ef2?file=/src/App.js – Freon
I'm sorry but it still does not work on my side πŸ€” Even in another sandbox. I created an issue on GitHub with more details – Caritacaritas
This is flat out incorrect. The Link component's to prop takes a Partial<Location> object or a string type, not any number. reactrouter.com/docs/en/v6/components/link – Amora
It definitely works with -1. I've been using it on multiple projects. It works as intended. Not just me, as the other person pointed, it works for them too. It does take -1 as a value no matter what their documentation says. – Freon
What other person? sandrina-p said it didn't work for them. I also just retried your sandbox, and it didn't work as expected, or consistently, for me either. If it's working for you at all then I'd say that's a happy accident. – Amora
C
3

As far as I know, it's impossible to have a fully accessible "Go Back" link with:

  <Link to={-1}>Go back</Link>
  // or
  <button onClick={() => navigate(-1)}>Go back</button>

It's not fully accessible for 2 reasons:

  1. Click does not work when you come directly from the first page (on mount).
  2. Right-click (open in a new tab) never works.

For 1) I found a workaround:

const router = useRouter(); // next/router

function handleGoBack() {
   // πŸ’‘ Verify if previous page exists before using router.back
    const hasPreviousPage = window.history.length > 1;

    if (hasPreviousPage) {
      router.back();
    } else {
      // fallback to a meaningful route.
      router.push("/");
    }
}

<button onClick={handleGoBack}>
  Go back
</button>

For 2) I didn't find any solution. My recommendation would be to avoid "go back" links using -1 whenever you can, in favor of using <Link> with a real URL to the possible previous page.

Caritacaritas answered 19/5, 2023 at 16:34 Comment(1)
Workaround 2 could be: use a <button onClick={(e) => { history.back(); }} />Go Back</button> – Nannettenanni
T
0

As described in this answer on a different question, the way you can implement the go back behaviour with accessible links in React Router 6 is to use the location state to store the path value which you want to go back to, then read it in the component which holds the link.

// COMPONENT 1
const { pathname } = useLocation();
const navigate = useNavigate();
// either of the following
<Link to="/destination" state: { previous: pathname }>
  CLICK ME
</Link>
<Button
  onClick= {() => {
    navigate(
      `/destination`,
      { state: { previous: pathname } }
    )
  }
>
  CLICK ME
</Button>

// COMPONENT 2
const { state: { previous }} = useLocation();
<Link href={ previous }>GO BACK</Link>
Tijuanatike answered 29/5, 2023 at 14:20 Comment(0)
S
-1

Try this one to go the previous page.

<Link to="..">Go Back</Link>
Sundin answered 18/6, 2024 at 21:28 Comment(0)
C
-1

You can add a relative property to your link

relative="path"

<Link to=".." relative="path"> Go back</Link>
Conformity answered 31/7, 2024 at 8:56 Comment(0)
K
-2

This might work...

let url = '\\peviouspagename.js';
let element = <Link to={url}>Go Back</Link>

Place anywhere before your function...

In the function, you'll have something like: <div>{element}</div> where the script is normally to go. Element is the <Link> script. State the URL separate, the page name is all it needs. You can hash <div id="hash"></div> as well by adding it to to the end like so: let url = '\\peviouspagename.js#hash'; doing so should take you directly to the that <div> onClick.

Kissie answered 19/6, 2022 at 10:34 Comment(3)
I did not understand your proposal. Could you integrate it in this codesandbox? codesandbox.io/s/a11y-into-js-forked-7oq2vq?file=/src/App.js – Caritacaritas
Mmm... my apologies. I am currently experiencing the same issues w/ reactjs. My current "working" solution is displayed here: #72640265 It partially works for me. Instead here I'm telling it where to go explicitly rather then go back... my issue is its the same page so it takes me to the section, then tells me no page found. Ironically the same issue I found trying in your sandbox. It takes me to the page, but won't display page. – Kissie
I'm going to keep an eye on this page tho. Especially on the Bug ticket. Not sure what I'm missing. Tried building a router page into my own application as well but, that didn't solve the problem either. Someone told me with the react, I have to have the page I want it to go to IN the router folder? Might recommend giving that a go. Good luck! – Kissie

© 2022 - 2025 β€” McMap. All rights reserved.