react-router: does not understand external URL with protocol
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.
About this issue
- Original URL
- State: closed
- Created 9 years ago
- Comments: 20 (6 by maintainers)
<Link/>is a router-aware anchor, if you want to link to an external site, use an<a/>.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.
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
<Link>doesn’t understand how to deal with both, then I need to perform the logic myself that distinguishes between external URLs and routes and renders different elements accordingly.Seems it would be nicer for react-router users if the provided
<Link>did this for them. For the situation described above, I’d probably have to end up writing another component wrapping this logic and rendering either a<Link>or an<a>accordingly — don’t other react-router users want the same thing?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
<a>clicks and checks whether they apply to routes: https://github.com/visionmedia/page.js/blob/master/index.js#L539)Note, you could make your own Link that does the check and then renders an
<a/>or a<Link/>I guess the docs are wrong. Instead of full URLs it should say full paths. For external links, just use
<a href>.Thanks for the tip, @ryanflorence. I ended up writing this component to handle both:
I think everyone that uses React-Router end up writing a component like that. Good or Bad IDK but annoying indeed 😛
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?
Try to use this condition directly
My solution, including a no
tooption, an external link and an internal link:Cannot remove that children (and let react use the
props.childrenfrom{...props}) because a11y complains about the<a>not having a manual children even if they have from the{...props}.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:
I created something like this if it helps: https://gist.github.com/shprink/bf9599e1d66b9dc4d151e89c1199ccb8
This should probably be covered in the
<Link />component documentation. It is completely unexpected behavior right now.The docs are misleading through omission – they say that a location object can be provided as the
toprop, but do not mention that the protocol and origin properties within that location object are ignored, or that a full url string as thetoprop will be applied relatively:href="http://a.example.com/http://b.example.com"instead ofhref="http://b.example.com"