将React-Router链接包装在html按钮中


Answers:


165

尽管这将在网络浏览器中呈现,但请注意:
⚠️将html嵌套在htmlbuttona(反之亦然)不是有效的html⚠️。如果要将HTML语义保留给屏幕阅读器,请使用另一种方法。

以相反的方式包装,您将获得带有链接的原始按钮。无需更改CSS。

 <Link to="/dashboard">
     <button type="button">
          Click Me!
     </button>
 </Link>

这里的按钮是HTML按钮。它也适用于从第三方库(如Semantic-UI-React)导入的组件。

 import { Button } from 'semantic-ui-react'
 ... 
 <Link to="/dashboard">
     <Button style={myStyle}>
        <p>Click Me!</p>
     </Button>
 </Link>

1
谢谢,简单而又有效,而@ChaseJames的CSS解决方案不起作用。也许有什么缺失。但是我正在使用引导程序; import { Button } from 'react-bootstrap';
Stefano Scarpanti

3
在文档中切换时,您将跳到锚点,然后再跳到按钮。为了避免这种情况,请将tabindex =“-1”添加到Link元素。通过按Enter激活按钮后,仍将链接该链接(至少在Firefox中...)。
tremby

4
如您所知,Link创建了定位标记,<a href="">并且定位标记不能包含按钮标记。
taher

4
尽管这似乎可行,但从语义上来说是错误的(在HTML 5中无效)。请参见可以使用HTML5在<a>内嵌套<button>元素吗?
imgx64 '18

例如,如果您将按钮禁用,则单击按钮仍将起作用。与该history.push选项相比,确实没有理由使用这种hacky解决方案
Burak

113

LinkButton 组件-React Router v4的解决方案

首先,关于这个问题的许多其他答案的注释。

Nest️嵌套<button><a>无效html。⚠️

这里给出的任何暗示将html嵌套button在React RouterLink组件中(反之亦然)的答案都将在Web浏览器中呈现,但这不是语义,可访问性或有效的html:

<a stuff-here><button>label text</button></a>
<button><a stuff-here>label text</a></button>

点击验证此标记与validator.w3.org来

这可能会导致布局/样式问题,因为通常不会将按钮放置在链接内部。


<button>在React Router<Link>组件中使用html标签。

如果您只想要htmlbutton标签...

<button>label text</button>

……然后,这是获得与React RouterLink组件一样工作的按钮的正确方法……

使用React Router的withRouter HOC将这些道具传递给您的组件:

  • history
  • location
  • match
  • staticContext

LinkButton 零件

这是LinkButton您复制/粘贴面食的组件:

// file: /components/LinkButton.jsx
import React from 'react'
import PropTypes from 'prop-types'
import { withRouter } from 'react-router'

const LinkButton = (props) => {
  const {
    history,
    location,
    match,
    staticContext,
    to,
    onClick,
    // ⬆ filtering out props that `button` doesn’t know what to do with.
    ...rest
  } = props
  return (
    <button
      {...rest} // `children` is just another prop!
      onClick={(event) => {
        onClick && onClick(event)
        history.push(to)
      }}
    />
  )
}

LinkButton.propTypes = {
  to: PropTypes.string.isRequired,
  children: PropTypes.node.isRequired
}

export default withRouter(LinkButton)

然后导入组件:

import LinkButton from '/components/LinkButton'

使用组件:

<LinkButton to='/path/to/page'>Push My Buttons!</LinkButton>

如果需要onClick方法:

<LinkButton
  to='/path/to/page'
  onClick={(event) => {
    console.log('custom event here!', event)
  }}
>Push My Buttons!</LinkButton>

更新:如果您正在寻找编写上述内容后可用的另一个有趣选项,请查看此useRouter钩子


13
这应该是公认的答案。所有其他答案都是恕我直言,骇客,并且可以提供意想不到的结果。谢谢!
凯尔(Kyle)'18年

组件的用法会进入的<div> .. </div元素内App.js吗?
DJ2

@ DJ2 -是的,或以任何其他组件要在使用它。
博史密斯

谢谢你!在我的特定用例中,我使用导入了material-ui按钮,import IconButton from '@material-ui/core/IconButton';并使用代替<button />它,它的效果很好。
丹·埃文斯

1
@Melounek-你好!如果目标是使<a>html标记的外观看起来像一个“按钮”,则@ChaseJames解决方案可以实现这一点。上面的问题问如何使用<button>html元素,而不是<a>
博·史密斯,

37

为什么不使用与按钮相同的CSS装饰链接标记。

<Link 
 className="btn btn-pink"
 role="button"
 to="/"
 onClick={this.handleClick()}
> 
 Button1
</Link>

我将把它作为最后的手段,主要是因为我已经完成了我需要的所有按钮的CSS,但感谢您的建议
Jose Rivera

出色的解决方案。对于蓝图,我以这种方式进行:<Link className = {[Classes.BUTTON,Classes.MINIMAL,Classes.ICON +“-” + IconNames.PLUS] .join(“”)} to = {“ / link”}>链接</ Link>
caiiiycuk

13

如果您正在使用react-router-dom并且material-ui可以使用...

import { Link } from 'react-router-dom'
import Button from '@material-ui/core/Button';

<Button component={Link} to="/open-collective">
  Link
</Button>

您可以在这里阅读更多内容。


由于必须强制to启用,Link因此该解决方案不适用于TS 。
目录

这就像一个魅力,谢谢
Pedro Silva

11

react-router v5.1.0开始,您可以使用useHistory 钩子

useHistory挂钩使您可以访问可用于导航的历史记录实例。

import React from 'react'
import { useHistory } from 'react-router'

export default function SomeComponent() {
  const { push } = useHistory()
  ...
  <button
    type="button"
    onClick={() => push('/some-link')}
  >
    Some link
  </button>
  ...
}

您可以将“ some-link”推送到该功能吗?
鲁西诺

在2020年这对我不起作用。在我的React版本中,useHistory为null
bikeman868

7

我使用Router和<Button />。否<链接/>

<Button onClick={()=> {this.props.history.replace('/mypage')}}>
   HERE
</Button>

1
我认为这应该是默认的解决方案,但是也许有些细节对我来说丢失了?支持的任何组件/节点/元素都onClick={ () => navigateTo(somePath) }可以使用此方法。是否使用redux和/import {push} from 'connected-react-router'或仅history.push(或替换)您的答案。
Thomas Fauskanger

6

5
因此,我尝试了一下,得到的是一个按钮,该按钮的中心有一个可单击的小链接,可充当其功能。但是,单击按钮上除链接以外的其他任何地方都无济于事。
何塞·里维拉

您可以使用CSS设置按钮样式,以确保其尺寸正确。例如,将其设置为widthheight
Raphael Rafatpanah

2
您可以对按钮标签使用内联样式。或者,您可以使用许多“ JS中的CSS”库之一。我更喜欢styled-componentsgithub.com/styled-components/styled-components
Raphael Rafatpanah '17

1
它适用于您的最新答案。非常感谢!
何塞·里维拉

5
这是不正确的...您应该包装按钮,而不是链接😱–
bensampaio

6

对于使用React 16.8+(挂钩)和React Router 5寻找解决方案的任何人:

您可以使用带有以下代码的按钮来更改路线:

<button onClick={() => props.history.push("path")}>

React Router为您的组件提供了一些支持,包括历史记录上push()函数,其功能与<Link to ='path'>元素非常相似。

您无需使用高阶组件“ withRouter”包装组件即可访问这些道具。


这对我来说很好;尽管我不确定这个解决方案是针对React 16.8+还是钩子的。只要您使用BrowserRouter(基于HTML历史记录API)而不是使用,我认为您的状况就很好HashRouter
pglezen

3

使用样式化的组件可以轻松实现

首先设计一个样式按钮

import styled from "styled-components";
import {Link} from "react-router-dom";

const Button = styled.button`
  background: white;
  color:red;
  font-size: 1em;
  margin: 1em;
  padding: 0.25em 1em;
  border: 2px solid red;
  border-radius: 3px;
`
render(
    <Button as={Link} to="/home"> Text Goes Here </Button>
);

检查样式化组件的主页以获取更多信息


3

React Router版本6的更新:

这里的各种答案就像反应路由器演进的时间表line

使用react-router v6中的最新钩子,现在可以通过useNavigate钩子轻松完成此操作。

import { useNavigate } from 'react-router-dom'      

function MyLinkButton() {
  const navigate = useNavigate()
  return (
      <button onClick={() => navigate("/home")}>
        Go Home
      </button>
  );
}

1

许多解决方案都专注于使事情复杂化。

对于与链接到应用程序其他位置的按钮一样简单的事情,使用withRouter是一个非常长的解决方案。

如果您要使用SPA(单页应用程序),我发现最简单的答案是与按钮的等效className一起使用。

这样可以确保您保持共享状态/上下文,而无需像这样完成整个应用程序的重新加载。

import { NavLink } from 'react-router-dom'; // 14.6K (gzipped: 5.2 K)

// Where link.{something} is the imported data
<NavLink className={`bx--btn bx--btn--primary ${link.className}`} to={link.href} activeClassName={'active'}>
    {link.label}
</NavLink>

// Simplified version:
<NavLink className={'bx--btn bx--btn--primary'} to={'/myLocalPath'}>
    Button without using withRouter
</NavLink>

这对我不起作用。按钮的最爱样式丢失了v_v。
sbstnssndn

也许您的悬停样式过于严格?他们被分配给button.myClassName吗?从样式选择器中删除按钮。或在scss中扩展它。
Acts7Seven19年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.