การห่อลิงก์ตอบกลับเราเตอร์ในปุ่ม html


109

โดยใช้วิธีการที่แนะนำ: นี่คือผลที่ได้: การเชื่อมโยงในปุ่ม , รหัสในระหว่างเส้นแสดงความคิดเห็น

ฉันสงสัยว่ามีวิธีห่อLinkองค์ประกอบจาก'react-router'ในbuttonแท็กHTML โดยใช้ react หรือไม่

ขณะนี้ฉันมีLinkส่วนประกอบสำหรับนำทางหน้าต่างๆในแอปของฉัน แต่ฉันต้องการแมปฟังก์ชันนั้นกับปุ่ม HTML

ใส่คำอธิบายภาพที่นี่ ใส่คำอธิบายภาพที่นี่

คำตอบ:


170

แม้ว่าสิ่งนี้จะแสดงในเว็บเบราว์เซอร์ แต่โปรดระวังว่า:
⚠️การซ้อน html buttonใน html a(หรือกลับกัน) ไม่ใช่ html ที่ถูกต้อง ⚠️ หากคุณต้องการคงความหมาย html ไว้กับโปรแกรมอ่านหน้าจอให้ใช้แนวทางอื่น

ทำการห่อในทางกลับกันและคุณจะได้ปุ่มดั้งเดิมพร้อมกับลิงค์ที่แนบมา ไม่จำเป็นต้องเปลี่ยนแปลง CSS

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

ปุ่มนี้คือปุ่ม HTML นอกจากนี้ยังมีผลบังคับใช้กับส่วนประกอบที่นำเข้าจากห้องสมุดบุคคลที่สามเช่นความหมาย-UI-ตอบสนอง

 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" ในองค์ประกอบลิงก์ ลิงก์จะยังคงตามมา (อย่างน้อยใน Firefox ... ) เมื่อเปิดใช้งานปุ่มโดยกด Enter
tremby

4
ดังที่คุณทราบลิงค์สร้างแท็ก<a href="">จุดยึดและแท็กจุดยึดต้องไม่มีแท็กปุ่ม
taher

4
แม้ว่าสิ่งนี้จะได้ผล แต่ก็มีความผิดทางความหมาย (และไม่ถูกต้องใน HTML 5) ดูฉันสามารถซ้อนองค์ประกอบ <button> ภายใน <a> โดยใช้ HTML5 ได้หรือไม่
imgx64

ตัวอย่างเช่นหากคุณทำให้ปุ่มของคุณถูกปิดการใช้งานการคลิกปุ่มจะยังคงใช้งานได้ ไม่มีเหตุผลที่จะใช้โซลูชันhistory.push
Burak

114

LinkButton คอมโพเนนต์ - โซลูชันสำหรับ React Router v4.2

อันดับแรกหมายเหตุเกี่ยวกับคำตอบอื่น ๆ สำหรับคำถามนี้

⚠️ทำรัง<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 …

การใช้งานตอบสนองของ 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 hookนี้


15
นี่ควรเป็นคำตอบที่ได้รับการยอมรับ คำตอบอื่น ๆ ทั้งหมดคือ IMHO แฮ็กและสามารถให้ผลลัพธ์ที่ไม่คาดคิดได้ ขอขอบคุณ!
Kyle

การใช้ส่วนประกอบจะอยู่ใน<div> .. </divองค์ประกอบของApp.jsหรือไม่
DJ2

@ DJ2 - ใช่หรือในส่วนประกอบอื่น ๆ ที่คุณต้องการใช้
Beau Smith

ขอบคุณสำหรับสิ่งนี้! ในกรณีการใช้งานโดยเฉพาะของฉันฉันนำเข้าปุ่ม material-ui ด้วยimport IconButton from '@material-ui/core/IconButton';และใช้ปุ่มนั้นแทน<button />และใช้งานได้ดี
Dan Evans

1
@Melounek - สวัสดี! หากเป้าหมายคือการมี<a>แท็ก html ที่มีลักษณะเป็น "ปุ่ม" แสดงว่าใช่โซลูชัน @ChaseJames จะทำได้ คำถามด้านบนถามวิธีใช้<button>องค์ประกอบ html ไม่ใช่<a>ไฟล์.
Beau Smith

38

ทำไมไม่เพียงตกแต่งแท็กลิงค์ด้วย 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

คุณไม่สามารถใช้สถานะเปิด / ปิดใช้งานบนปุ่มปลอม
maco

16

หากคุณกำลังใช้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 เนื่องจากจำเป็นต้องใช้toprop on Link
ไดเรกทอรี

11

คุณสามารถใช้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>
  ...
}

คุณสามารถพุช "some-link" ไปที่ฟังก์ชันได้หรือไม่
Rushino

ในปี 2020 สิ่งนี้ไม่ได้ผลสำหรับฉัน useHistory เป็นโมฆะใน React เวอร์ชันของฉัน
bikeman868

7

ฉันใช้เราเตอร์และ <ปุ่ม /> ไม่มี <Link />

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

1
ฉันคิดว่านี่ควรเป็นโซลูชันเริ่มต้น แต่รายละเอียดบางอย่างอาจสูญหายไป? ส่วนประกอบ / โหนด / องค์ประกอบใด ๆที่สนับสนุนonClick={ () => navigateTo(somePath) }สามารถใช้แนวทางนี้ได้ ไม่ว่าจะใช้ redux และimport {push} from 'connected-react-router'หรือ just history.push(หรือแทนที่) เหมือนในคำตอบของคุณ
Thomas Fauskanger

6

5
ดังนั้นฉันจึงลองสิ่งนี้และสิ่งที่ฉันได้รับคือปุ่มที่มีลิงค์ขนาดเล็กที่คลิกได้ตรงกลางซึ่งทำหน้าที่ของมัน อย่างไรก็ตามคลิกที่ใดก็ได้บนปุ่ม แต่ลิงก์โดยตรงไม่ได้ทำอะไรเลย
Jose Rivera

คุณสามารถใช้ CSS เพื่อจัดรูปแบบปุ่มเพื่อให้แน่ใจว่ามีขนาดถูกต้อง ยกตัวอย่างเช่นการตั้งค่ามันและwidth height
Raphael Rafatpanah

2
คุณสามารถใช้รูปแบบอินไลน์ได้เช่นเดียวกับแท็กปุ่ม หรือคุณสามารถใช้ไลบรารี "css in JS" จำนวนมาก styled-componentsฉันชอบ github.com/styled-components/styled-components
Raphael Rafatpanah

1
ใช้ได้กับคำตอบที่อัปเดตของคุณ ขอบคุณมาก!
Jose Rivera

5
ไม่ถูกต้อง ... คุณควรปิดปุ่มไม่ใช่ลิงก์😱
bensampaio

6

สำหรับใครที่กำลังมองหาวิธีแก้ปัญหาโดยใช้React 16.8+ (hooks) และ React Router 5:

คุณสามารถเปลี่ยนเส้นทางโดยใช้ปุ่มที่มีรหัสต่อไปนี้:

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

React Router จัดเตรียมอุปกรณ์ประกอบฉากบางอย่างให้กับส่วนประกอบของคุณรวมถึงฟังก์ชันpush ()ในประวัติซึ่งทำงานเหมือนกับองค์ประกอบ <Link to = 'path'>

คุณไม่จำเป็นต้องห่อส่วนประกอบของคุณด้วยส่วนประกอบที่สูงกว่า "withRouter" เพื่อเข้าถึงอุปกรณ์ประกอบฉากเหล่านั้น


มันใช้ได้ดีสำหรับฉัน แม้ว่าฉันไม่แน่ใจว่าโซลูชันนี้เฉพาะสำหรับ React 16.8+ หรือ hooks ผมคิดว่าคุณอยู่ในรูปร่างที่ดีกับเรื่องนี้ตราบใดที่คุณจ้างBrowserRouter(ตามประวัติศาสตร์ API แบบ HTML) HashRouterแทน
pglezen

5

อัปเดตสำหรับ React Router เวอร์ชัน 6:

คำตอบต่างๆที่นี่เปรียบเสมือนเส้นเวลาของวิวัฒนาการของรีแอคชั่นเตอร์

การใช้ hooks ล่าสุดจาก react-router v6 ตอนนี้สามารถทำได้อย่างง่ายดายด้วยuseNavigatehook

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>

สิ่งนี้ไม่ได้ผลสำหรับฉัน รูปแบบของปุ่ม hove หายไป v_v
sbstnssndn

บางทีรูปแบบการวางเมาส์ของคุณอาจเข้มงวดเกินไป? พวกเขากำหนดให้ button.myClassName หรือไม่ ปุ่มลบออกจากตัวเลือกสไตล์ หรือขยายใน scss.
Acts7Seven
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.