React Router - 使用<Link>返回

9
在 React Router v6 中,我如何使用 <Link> 而不是 useNavigate() 返回到上一页?
// Instead of this...
<button onClick={() => navigate(-1)}>

// ...it needs to be this:
const previousPage = ???

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

将它更改为<Link>将允许我使用<a href="xxxx">而不是<button>,这是创建页面之间链接最易于访问的方式。(有关按钮与链接的更多信息)。例如,它允许用户右键单击并在新标签页中打开页面。

但我不知道要传递给Link的URL。

更新:我创建了一个codesandbox来帮助您找到解决方案。

更新2:根据答案和一些研究,我创建了一个 GitHub 问题以 react-router为基础

更新3:我在下面添加了自己的答案。

5个回答

8
react-router-dom@6 中并没有 bug,Link 并不是其真正意义上的作用,实际上它就是一个锚点标签,用于声明式导航到某个路径。这与像 history.go(1)history.back()(即 history.go(-1))等命令式操作本质上是不同的,因为你在这里是在命令式地告诉浏览器向前或向后导航历史记录栈。
然而,在 react-router-dom@6 中,你可以相对于当前路径进行导航。使用 ".." 会使任何在当前 Routes 组件内渲染的 Route 组件向后导航一个路径片段。例如:从 "/destiny" 回到使用同一 Routes 组件的 "/"
示例:
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>
  );
}

请注意,这不等同于navigate(-1),因为它没有经过历史记录栈的转换,所以它不是真正的后退导航。如果您想进行真正的后退导航,则需要向Link添加一个onClick处理程序,阻止默认事件操作,并处理发出命令式的后退导航。
例子:
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


1
是的,to={'..'} 是一种hack方法。使用 onClick 的解决方案并不完美,因为如果用户在新页面上打开链接(例如右键单击),它将无法转到与 navigate(-1) 相同的路由。 我认为解决方案是使用原生JS获取最近访问的页面,并将其设置为href。我明天稍后会尝试实现这一点。 - sandrina-p
抱歉,@sandrina-p,我不明白你关于onClick处理程序无法工作的评论,它使用了与其他地方相同的navigate(-1)。我在Github上看到了你的评论,你能否澄清一下关于不可访问性的评论?我无法理解关于打开新页面并使代码不进入预期目标的评论,所以也许我没有理解你具体指的是什么。 - Drew Reese
1
这是我制作的Loom视频,展示了这个问题。尝试在主页>中间>目标页面上右键单击“返回(-1)”。它会跳转到“主页”而不是“中间”页面。 - sandrina-p
1
@sandrina-p 我明白了,我猜测问题出在 ".." 解析为目标 URL 的方式上。就像我所说的那样,它不是技术上的后退导航,它导航到一个路径段向后/向上。除了提供 onClick 处理程序并覆盖默认的链接行为外,实际上没有任何锚点标记/链接的方法来发出返回导航。您可以尝试维护自己的历史记录堆栈,在应用程序状态中提供此作为任何链接的目标路径,以便导航到先前的位置。但请注意,这仍然不是后退导航,它将是 PUSH 而不是 POP。 - Drew Reese

2
据我所知,使用“返回”链接无法完全实现无障碍访问:
  <Link to={-1}>Go back</Link>
  // or
  <button onClick={() => navigate(-1)}>Go back</button>

它有两个原因导致无法全面访问:

  1. 当你直接从第一页进入时(在挂载时),点击不起作用。
  2. 右键(在新标签页中打开)永远不起作用。

对于1),我找到了一个解决方法:

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>

对于第二点,我没有找到任何解决方案。我的建议是尽可能避免使用-1作为“返回”链接,而是使用<Link>并提供一个真实的URL来指向可能的前一页。

1

<Link to={-1}>返回</Link> 将会生效。


哎呀,在这个 CodeSandbox 上,它没能正常工作。https://codesandbox.io/s/a11y-into-js-forked-7oq2vq?file=/src/App.js - sandrina-p
我刚在那个沙盒上进行了测试。看起来工作正常。这是我的分支版本。我重构了一些路由代码,使其更加简洁。https://codesandbox.io/s/a11y-into-js-forked-hx2ef2?file=/src/App.js - blessedcoder
这完全是错误的。Link 组件的 to 属性接受一个 Partial<Location> 对象 或者 一个 string 类型,而不是任何数字。https://reactrouter.com/docs/en/v6/components/link - Drew Reese
它绝对可以使用-1。我已经在多个项目中使用它。它按预期工作。不仅仅是我,正如其他人指出的那样,它也适用于他们。无论他们的文档说什么,它都将-1作为一个值。 - blessedcoder
什么其他人?sandrina-p说它对他们不起作用。我刚刚重新尝试了你的沙盒,但它并没有像预期的那样或者一致地为我工作。如果它对你有任何作用,那么我会说这是一个幸运的巧合。 - Drew Reese
显示剩余2条评论

0
此答案所述,您可以在React Router 6中使用位置状态来存储要返回的路径值,然后在包含链接的组件中读取它,以实现可访问链接的返回行为。
// 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>

-1

这可能会起作用...

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

在你的函数之前任何地方放置...

在函数中,你会有类似这样的东西:<div>{element}</div>,其中脚本通常要放置。元素是<Link>脚本。将URL分开,页面名称就足够了。你也可以通过像这样添加到结尾来哈希<div id="hash"></div>let url = '\\peviouspagename.js#hash'; 这样做应该会直接在单击时带您到那个<div>


我不理解你的建议。你能把它集成到这个 codesandbox 中吗?codesandbox.io/s/a11y-into-js-forked-7oq2vq?file=/src/App.js - sandrina-p
嗯...抱歉,我目前在使用reactjs时遇到了同样的问题。我的当前“工作”解决方案在这里显示:https://stackoverflow.com/questions/72639765/routing-how-do-you-fail-to-find-a-page-that-is-right-in-obviously-right-in-fron 对我部分起作用。相反,我在这里明确告诉它去哪里而不是返回...我的问题是它是同一页,所以它带我去了那个部分,然后告诉我找不到页面。具有讽刺意味的是,我在您的沙盒中尝试时发现了同样的问题。它带我到了页面,但无法显示页面。 - HiB
我会继续关注这个页面。特别是Bug ticket。不确定我错过了什么。也尝试将路由器页面构建到自己的应用程序中,但是也没有解决问题。有人告诉我,使用React时,我必须在路由器文件夹中放置要转到的页面?可能建议尝试一下。祝好运! - HiB

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接