Using suggested method: This is the result: A link in the button, Code in between comment lines
I was wondering if there is a way to wrap a Link
element from 'react-router'
in an HTML button
tag using react.
I currently have Link
components to navigate pages in my app, but I would like to map that functionality to my HTML buttons.
While this will render in a web browser, beware that:
??Nesting an html button
in an html a
(or vice-versa) is not valid html ??.
If you want to keep your html semantic to screen readers, use another approach.
Do wrapping in the reverse way and you get the original button with the Link attached. No CSS changes required.
<Link to="/dashboard">
<button type="button">
Click Me!
</button>
</Link>
Here button is HTML button. It is also applicable to the components imported from third party libraries like Semantic-UI-React.
import { Button } from 'semantic-ui-react'
...
<Link to="/dashboard">
<Button style={myStyle}>
<p>Click Me!</p>
</Button>
</Link>
LinkButton
component - a solution for React Router v4First, a note about many other answers to this question.
<button>
and <a>
is not valid html. ??Any answer here which suggests nesting a html button
in a React Router Link
component (or vice-versa) will render in a web browser, but it is not semantic, accessible, or valid html:
<a stuff-here><button>label text</button></a>
<button><a stuff-here>label text</a></button>
?Click to validate this markup with validator.w3.org ?
This can lead to layout/styling issues as buttons are not typically placed inside links.
<button>
tag with React Router <Link>
component.If you only want an html button
tag…
<button>label text</button>
…then, here's the right way to get a button that works like React Router’s Link
component…
Use React Router’s withRouter HOC to pass these props to your component:
history
location
match
staticContext
LinkButton
componentHere’s a LinkButton
component for you to copy/pasta:
// 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)
Then import the component:
import LinkButton from '/components/LinkButton'
Use the component:
<LinkButton to='/path/to/page'>Push My Buttons!</LinkButton>
If you need an onClick method:
<LinkButton
to='/path/to/page'
onClick={(event) => {
console.log('custom event here!', event)
}}
>Push My Buttons!</LinkButton>
Update: If you're looking for another fun option made available after the above was written, check out this useRouter hook.
Why not just decorate link tag with the same css as a button.
<Link
className="btn btn-pink"
role="button"
to="/"
onClick={this.handleClick()}
>
Button1
</Link>
If you are using react-router-dom
and material-ui
you can use ...
import { Link } from 'react-router-dom'
import Button from '@material-ui/core/Button';
<Button component={Link} to="/open-collective">
Link
</Button>
You can read more here.
You can use useHistory
hook since react-router v5.1.0.
The
useHistory
hook gives you access to the history instance that you may use to navigate.
import React from 'react'
import { useHistory } from 'react-router-dom'
export default function SomeComponent() {
const { push } = useHistory()
...
<button
type="button"
onClick={() => push('/some-link')}
>
Some link
</button>
...
}
I use Router and < Button/>. No < Link/>
<Button onClick={()=> {this.props.history.replace('/mypage')}}>
HERE
</Button>
For anyone looking for a solution using React 16.8+ (hooks) and React Router 5:
You can change the route using a button with the following code:
<button onClick={() => props.history.push("path")}>
React Router provides some props to your components, including the push() function on history which works pretty much like the < Link to='path' > element.
You don't need to wrap your components with the Higher Order Component "withRouter" to get access to those props.
Update for React Router version 6:
The various answers here are like a timeline of react-router's evolution
Using the latest hooks from react-router v6, this can now be done easily with the useNavigate
hook.
import { useNavigate } from 'react-router-dom'
function MyLinkButton() {
const navigate = useNavigate()
return (
<button onClick={() => navigate("/home")}>
Go Home
</button>
);
}
With styled components this can be easily achieved
First Design a styled button
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>
);
check styled component's home for more
Many of the solutions have focused on complicating things.
Using withRouter is a really long solution for something as simple as a button that links to somewhere else in the App.
If you are going for S.P.A. (single page application), the easiest answer I have found is to use with the button's equivalent className.
This ensures you are maintaining shared state / context without reloading your entire app as is done with
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>
Source: Stackoverflow.com