Обгортання посилання маршрутизатора з реакцією в кнопку html


108

Використання запропонованого методу: Це результат: Посилання на кнопку , Код між рядками коментарів

Мені було цікаво, чи є спосіб обернути Linkелемент із тегу 'react-router'HTML buttonза допомогою реакції.

В даний час у мене є Linkкомпоненти для навігації сторінками в моєму додатку, але я хотів би встановити цю функцію у свої кнопки HTML.

введіть тут опис зображення введіть тут опис зображення

Відповіді:


165

Хоча це відображатиметься у веб-браузері, пам’ятайте, що:
⚠️ Вкладання html buttonу html 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
Дякую, простий та робочий, тоді як css-рішення @ChaseJames не працює. Можливо, там чогось не вистачає. Але я використовую bootstrap; import { Button } from 'react-bootstrap';.
Stefano Scarpanti

3
Під час вкладки по документу ви переходите на прив'язку, а потім до кнопки окремо. Щоб цього уникнути, додайте tabindex = "- 1" до елемента Link. Посилання все одно буде переходити (принаймні у Firefox ...), коли кнопка активується натисканням клавіші enter.
трембі

4
Як відомо, Link створює тег <a href="">прив’язки, а прив’язка не може містити тег кнопок.
тахер

4
Хоча це, здається, працює, це семантично помилково (і неприпустимо в HTML 5). Див. Чи можу я вкласти елемент <button> всередину <a> за допомогою HTML5?
imgx64

Якщо ви, наприклад, вимкнете кнопку, натискання кнопки все одно спрацює. Насправді немає жодної причини використовувати це хакерське рішення порівняно з history.pushваріантом
Бурак,

113

LinkButton компонент - рішення для React Router v4

Спочатку примітка про багато інших відповідей на це питання.

Вкладений <button>і <a>не дійсний html. ⚠️

Будь-яка відповідь тут, яка пропонує вкласти html buttonу Linkкомпонент React Router (або навпаки), буде відображатися у веб-браузері, але вона не є семантичною, доступною чи дійсним html:

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

Клацніть, щоб перевірити цю розмітку за допомогою validator.w3.org

Це може призвести до проблем із макетом / стилем, оскільки кнопки зазвичай не розміщуються всередині посилань.


Використання <button>тегу html з <Link>компонентом React Router .

Якщо вам потрібен лише buttonтег html ...

<button>label text</button>

… Тоді ось правильний спосіб отримати кнопку, яка працює як Linkкомпонент React Router …

Використовуйте 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
Це має бути прийнятою відповіддю. Усі інші відповіді: IMHO - хакі та можуть дати несподівані результати. Дякую!
Кайл

Чи буде використання компонента всередині <div> .. </divелемента App.js?
DJ2,

@ DJ2 - Так, або в будь-якому іншому компоненті, в якому ти хочеш його використовувати.
Бо Сміт,

Дякую за це! У моєму конкретному випадку використання я імпортував кнопку material-ui з import IconButton from '@material-ui/core/IconButton';і використовував її замість, <button />і вона чудово працювала.
Ден Еванс

1
@Melounek - Привіт! Якщо метою є <a>тег html, візуально оформлений так, щоб виглядати як "кнопка", тоді рішення @ChaseJames досягає цього. Запитання вище задає питання, як використовувати <button>елемент html, а не файл <a>.
Beau Smith

37

Чому б просто не прикрасити тег посилання тим самим css, що і кнопка.

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

Я буду тримати це як крайній засіб, головним чином тому, що я зробив CSS для всіх потрібних мені кнопок, але дякую за пропозицію
Хосе Рівера,

Блискуче рішення. Для проекту я роблю таким чином: <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>

Детальніше ви можете прочитати тут .


Це рішення не буде працювати з TS, оскільки toпідтримка Linkобов’язкова.
каталог

Це працює як шарм, дякую
Педро Сільва,

10

Ви можете використовувати useHistory хук з реакційного маршрутизатора v5.1.0 .

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>
  ...
}

Чи можете ви натиснути "деяке посилання" на функцію?
Рушино

У 2020 році це не працює для мене. useHistory є нульовим у моїй версії React
bikeman868

7

Я використовую маршрутизатор і <Button />. Ні <Посилання />

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

1
Я думаю, що це має бути рішенням за замовчуванням, але, можливо, деякі деталі для мене втрачені? БУДЬ-ЯКИЙ компонент / вузол / елемент, що підтримує, onClick={ () => navigateTo(somePath) }може використовувати цей підхід. Чи використовуєте redux і import {push} from 'connected-react-router'чи просто history.push(або замінюєте), як у вашій відповіді.
Томас Фаускангер

6

5
Тож я спробував це, і що я отримав - це кнопка з невеликим посиланням, що можна натиснути в центрі, яка виконувала свою функцію. Однак натискання в будь-якому місці кнопки, але пряме посилання нічого не робило.
Хосе Рівера

Ви можете використовувати CSS для стилізації кнопки, щоб переконатися, що вона правильно розмірена. Наприклад, встановивши це widthі height.
Рафаель Рафатпанах

2
Ви можете використовувати вбудовані стилі так само для тегу кнопки. Або ви можете скористатися однією з багатьох бібліотек "css in JS". Я віддаю перевагу styled-components. github.com/styled-components/styled-components
Рафаель Рафатпанах

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(на основі API історії HTML) замість 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:

Різні відповіді тут схожі на часову шкалу розвитку реакційного маршрутизатора 🙂

Використовуючи найновіші гачки від response-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 (односторінковий додаток), найпростішою відповіддю, яку я знайшов, є використання з еквівалентним класом Імені кнопки.

Це гарантує, що ви підтримуєте спільний стан / контекст, не перезавантажуючи всю програму, як це було зроблено

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.
Acts7, Сім
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.