react-routerリンクをhtmlボタンでラップする


109

提案された方法を使用する: これが結果です:ボタンでリンクコードのコメント行の間に

reactを使用してHTMLタグ内のLink要素をラップする方法があるかどうか疑問に思い'react-router'ましたbutton

現在Link、アプリのページをナビゲートするコンポーネントがありますが、その機能をHTMLボタンにマップしたいと思います。

ここに画像の説明を入力してください ここに画像の説明を入力してください

回答:


170

これはWebブラウザーでレンダリングされますが、次の
点に注意してください。⚠️htmlにhtmlbuttonをネストするa(またはその逆)ことは有効な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 2017年

3
ドキュメントをタブで移動するときは、アンカーにタブで移動し、次にボタンに個別にタブで移動します。これを回避するには、Link要素にtabindex = "-1"を追加します。Enterキーを押してボタンをアクティブにした場合でも、リンクは(少なくともFirefoxでは...)追跡されます。
震え2017年

4
ご存知のように、リンクはアンカータグ<a href="">を作成し、アンカータグにボタンタグを含めることはできません。
タヘル

4
これは機能しているように見えますが、意味的に間違っています(HTML 5では無効です)。HTML5を使用して<a>内に<button>要素をネストできますか?を
imgx64 2018年

たとえば、ボタンを無効にしても、ボタンをクリックしても機能します。比較すると、このハックソリューションを使用する理由は本当にありませんhistory.pushオプション
ブラク

114

LinkButton コンポーネント-ReactRouterv4のソリューション

まず、この質問に対する他の多くの回答についてのメモ。

⚠️ネスト<button>して<a>おり、有効なhtmlではありません。⚠️

buttonReact RouterLinkコンポーネントにhtmlをネストすること(またはその逆)を提案するここでの回答は、Webブラウザーでレンダリングされますが、セマンティック、アクセス可能、または有効なhtmlではありません。

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

クリックして、validator.w3.orgでこのマークアップを検証します

ボタンは通常リンク内に配置されないため、これはレイアウト/スタイルの問題につながる可能性があります。


<button>ReactRouter<Link>コンポーネントでhtmlタグを使用する。

htmlbuttonタグのみが必要な場合…

<button>label text</button>

…次に、ReactRouterのLinkコンポーネントのように機能するボタンを取得する正しい方法は次のとおりです…

ReactRouterwithRouterHOCを使用して、これらの小道具をコンポーネントに渡します。

  • 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フックを確認してください


15
これは受け入れられた答えでなければなりません。他のすべての答えは、私見、ハックであり、予期しない結果をもたらす可能性があります。ありがとうございました!
カイル

コンポーネントの使用法はの要素の内部<div> .. </divに入りApp.jsますか?
DJ2 2018年

@ DJ2 -はい、または任意の他の構成要素で、あなたはそれを使用したい。
ボー・スミス

これをありがとう!私の特定のユースケースでは、material-uiボタンをインポートし、import IconButton from '@material-ui/core/IconButton';代わりに<button />それを使用しましたが、うまく機能しました。
ダン・エヴァンス

1
@ Melounek-こんにちは!目標が<a>「ボタン」のように見えるように視覚的にスタイル設定されたhtmlタグを持つことである場合、はい@ChaseJamesソリューションはこれを達成します。上記の質問は<button>、ではなくhtml要素を使用する方法を尋ねています<a>
BeauSmith19年

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"}>リンク</リンク>
caiiiycuk

偽のボタンで有効/無効状態を使用することはできません。
MACO

16

あなたが使用している場合react-router-dommaterial-ui、あなたは使用することができます...

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

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

あなたはここでもっと読むことができます


toprop onLinkは必須であるため、このソリューションはTSでは機能しません。
ディレクトリ

11

react-routerv5.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年には、これは私にはうまくいきません。useHistoryが反応の私のバージョンではnullです
bikeman868

7

ルーターと<ボタン/>を使用しています。いいえ<リンク/>

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

1
これがデフォルトの解決策になるはずだと思いますが、おそらくいくつかの詳細が私に失われていますか?サポートするすべてのコンポーネント/ノード/要素がonClick={ () => navigateTo(somePath) }このアプローチを使用できます。あなたの答えのようにreduxを使用するか、import {push} from 'connected-react-router'または単にhistory.push(または置換する)かどうか。
ThomasFauskanger18年

6

5
それでこれを試してみたところ、中央に小さなクリック可能なリンクが付いたボタンがその機能を果たしていました。ただし、ボタンの他​​の場所をクリックしても、直接リンクは何もしませんでした。
ホセ・リベラ

CSSを使用してボタンのスタイルを設定し、ボタンのサイズが正しくなるようにすることができます。例えば、それを設定することだwidthheight
ラファエルラファトパナ2017

2
ボタンタグにも同じようにインラインスタイルを使用できます。または、多くの「cssinJS」ライブラリの1つを使用できます。私は好きstyled-componentsです。 github.com/styled-components/styled-components
Raphael Rafatpanah 2017

1
それはあなたの更新された答えで機能しました。どうもありがとうございます!
ホセ・リベラ

5
これは正しくありません...あなたはボタンではなく、リンクを😱ラップする必要があります
bensampaio

6

React 16.8+(フック)とReact Router 5を使用したソリューションをお探しの方へ:

次のコードのボタンを使用してルートを変更できます。

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

React Routerは、<Link to = 'path'>要素とほとんど同じように機能する履歴のpush()関数など、コンポーネントにいくつかの小道具を提供します。

これらの小道具にアクセスするために、コンポーネントを高次コンポーネント「withRouter」でラップする必要はありません。


これは私にとっては問題なく機能します。このソリューションがReact16.8 +またはフックに固有のものかどうかはわかりませんが。のBrowserRouter代わりに(HTML履歴APIに基づいて)使用している限り、これで問題はないと思いますHashRouter
pglezen

5

Reactルーターバージョン6のアップデート:

ここでのさまざまな答えは、react-routerの進化のタイムラインのようなものです🙂

react-router v6の最新のフックを使用して、これをuseNavigateフックで簡単に実行できるようになりました。

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

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

バージョン6はまだ利用できません。そのため、この回答は混乱を招きます。このコメントの時点で最新のものは5.2.0です。
davidawad

バージョン6は現在ベータ版で利用可能であり、一部のプロジェクトで使用されています。こちらの[バージョン]タブをご覧ください:npmjs.com/package/react-router
JM Rossy

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>
);

詳細については、スタイル付きコンポーネントのホームを確認してください


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で拡張します。
Acts7Seven
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.