-
-
Notifications
You must be signed in to change notification settings - Fork 10.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
<Link> does not understand external URL with protocol #1147
Comments
I guess the docs are wrong. Instead of full URLs it should say full paths. For external links, just use |
If that's the case, then (with docs clarified) this issue still stands but as a feature request rather than a bug. (Also, it's confusing that the external links work without a protocol?) Let's say I have an array of objects representing 20 links, a few of which are "routes" and a few of which are true URLs. I want to map those to components and render them. If Seems it would be nicer for react-router users if the provided Or if other people know of a good existing way (or a better non-existing way) to take care of that use-case, I'd love to hear it. (e.g. page.js hijacks any |
|
Note, you could make your own Link that does the check and then renders an var YourLink = React.createClass({
render () {
return this.isExternal() ? <a/> : <Link/>
}
}); |
I agree with @davidtheclark . I just ran into this issue and began implementing my own component similar to the one you describe above to handle the logic, but it seemed so basic and obvious a concern and such a common scenario that I stopped to check the react-router docs and issues for the "built-in" solution that I was certain existed. I am surprised that this feature is not built-in. |
I think everyone that uses React-Router end up writing a component like that. Good or Bad IDK but annoying indeed :P |
I created something like this if it helps: https://gist.github.com/shprink/bf9599e1d66b9dc4d151e89c1199ccb8 |
I agree with @shprink and @davidtheclark. If you want to handle dynamic routes (which nearly every app does), you'll have to add this functionality. Is there any reason that a URL with a protocol and a different domain should NOT be honored? @ryanflorence, would you merge a PR if I added this functionality for you? |
As currently set up this wouldn't be the correct place to put this logic – this ought instead to be handled by the history. |
Thanks for the tip, @ryanflorence. I ended up writing this component to handle both: import React, { Component, PropTypes } from 'react';
import { Link } from 'react-router';
import isExternal from 'is-url-external';
const propTypes = {
to: PropTypes.string.isRequired,
};
/**
* Link that also works for external URL's
*/
export default class LinkDuo extends Component {
render() {
return isExternal(this.props.to) ?
<a
href={this.props.to}
{...this.props}
/>
:
<Link {...this.props} />;
}
}
LinkDuo.propTypes = propTypes; |
Try to use this condition directly
|
I wasn't able to use the /* @flow */
import * as React from 'react';
import { Link as LinkImport } from 'react-router-dom';
import validator from 'validator';
type PropsFlowType = {
to: string | Object,
};
const Link = ({
to,
...otherProps
}: PropsFlowType): React.Node => (
validator.isURL(to)
? (
<a
href={to}
{...otherProps}
/>
) : (
<LinkImport
to={to}
{...otherProps}
/>
)
);
export default Link; |
This should probably be covered in the The docs are misleading through omission – they say that a location object can be provided as the |
Since I needed a TypeScript implementation with as few external dependencies as possible I made this drop in replacement of the Link class in react-router-dom (with the help of all your comments). It might be of help to some of you as well: import * as React from 'react';
import { Link as RouterLink } from 'react-router-dom';
export default class Link extends React.Component<any, {}> {
constructor(props: any) {
super(props);
}
render(): JSX.Element {
return /^https?:\/\//.test(this.props.to)
? <a href={this.props.to} {...this.props} />
: <RouterLink {...this.props} />
}
} |
+1 for either adding this functionality or at min adding it to the docs. Spent a day trying to figure out why the app wouldn't link to external sources. |
My solution, including a no // What <Link> should always be
import React from 'react';
import { Link } from 'react-router-dom';
export default ({ to, children, ...props }) => {
// It is a simple element with nothing to link to
if (!to) return <span {...props}>{children}</span>;
// It is intended to be an external link
if (/^https?:\/\//.test(to)) return <a href={to} {...props}>{children}</a>;
// Finally, it is an internal link
return <Link to={to} {...props}>{children}</Link>;
}; Cannot remove that children (and let react use the |
I created a render props component which you pass the url, a renderInternal function, and a renderExternal function as props. It then checks if the link is internal or external, and calls either renderInternal or renderExternal. That way there's no messing around with trying to pass through any React-Router props, you can just pass your usual React-Router component to renderInternal Looks a bit like this:
example usage:
If gives you complete flexibility over any classes or props you want to pass to or . Hope that helps! |
This comment has been minimized.
This comment has been minimized.
Let's re-open this until we can add some notes to the docs about using external links and add a warning for URLs with anything more than just a path in |
Actually, I'm thinking we just make We should get this fixed in v5 and make sure it works in v6 too. |
If I use
<Link to='//google.com'>
it's fine; but if I use<Link to='http://google.com'>
I get an error:Uncaught Error: Invariant Violation: Cannot find a route named "http://google.com"
.Based on the docs, I believe the
<Link>
component is supposed to handle full URLs as well as routes, so this appears to be a bug.The text was updated successfully, but these errors were encountered: