288

Since I'm using React Router to handle my routes in a React app, I'm curious if there is a way to redirect to an external resource.

Say someone hits:

example.com/privacy-policy

I would like it to redirect to:

example.zendesk.com/hc/en-us/articles/123456789-Privacy-Policies

I'm finding exactly zero help in avoiding writing it in plain JavaScript at my index.html loading with something like:

if (window.location.path === "privacy-policy"){
  window.location = "example.zendesk.com/hc/en-us/articles/123456789-Privacy-Policies"
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Eric Hodonsky
  • 5,617
  • 4
  • 26
  • 36
  • 1
    Which React Router are you using? – Tyler McGinnis Mar 20 '17 at 21:55
  • 1
    I'm using version 3.x – Eric Hodonsky May 16 '17 at 00:10
  • 2
    Simply change `window.location.href` to have a formal redirection. – Amirhossein Mehrvarzi Mar 02 '19 at 19:02
  • 4
    @AmirhosseinMehrvarzi that doesn't actually mean anything. Could you be more specific or give an example? Also I'm not sure if you've noticed but this question already has an accepted answer dealing with React & React Router which is what the question was about. – Eric Hodonsky Mar 04 '19 at 15:59
  • 1
    @Relic You need to use that as your url in your if condition. I had similar problem a few days ago and found this way simple and effective. It redirects immediately. **Accepted answer** is a *Routing solution* (While it violates Route principles, considering that Route architecture is for **navigation inside the App** not for outside) which doesn't work for any environment like mine – Amirhossein Mehrvarzi Mar 04 '19 at 19:06
  • @AmirhosseinMehrvarzi the redirect is instant regardless... – Eric Hodonsky Mar 05 '19 at 20:08
  • @AmirhosseinMehrvarzi This question is very specific and the solution here speaks too it. It was looking for something that broke them because there was no 'redirect' built into this router which IS part of routing principals. Consider 301 & 302. The accepted answer is exactly a redirect. Which, because it can't carry the response headers is not a great idea but when you have a SPA with no domain hits from URIs there no way to do it from the server / cloudfront. This is the only solution within React for the OP. – Eric Hodonsky Mar 05 '19 at 20:11
  • Also @AmirhosseinMehrvarzi if you're not using the react environment this question isn't for you, nor is the answer. So it makes sense it doesn't work. – Eric Hodonsky Mar 05 '19 at 20:12
  • @Relic No :-). I had a React project. The meaning of environment is using `js` or `ts`, `es2015` or .... They affect the solution. I used my solution and is working properly. To continue conversation please go to chatroom. Here is forbidden. Thanks. – Amirhossein Mehrvarzi Mar 05 '19 at 20:25
  • @AmirhosseinMehrvarzi those things were irrelevant... and I'm glad you found your own solution. If you notice I found my own solution too :D – Eric Hodonsky Mar 06 '19 at 21:08
  • window.location.href may cause cross scripting issue right ? is there a way to work around that ? – user2128 Feb 03 '21 at 02:55

26 Answers26

301

Here's a one-liner for using React Router to redirect to an external link:

<Route path='/privacy-policy' component={() => {
    window.location.href = 'https://example.com/1234';
    return null;
}}/>

It uses the React pure component concept to reduce the component's code to a single function that, instead of rendering anything, redirects browser to an external URL.

It works both on React Router 3 and 4.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Evgeny Lukianchikov
  • 3,851
  • 3
  • 15
  • 9
  • 4
    This works but I was looking for a more elegant scalable solution. See what I came up with as it allowed me to go even further with redirects for MobileApps etc ( Not ReactNative, truly Native apps ). Now what I'm doing isn't the right way to solve my problem, but to solve this problem I suggest you investigate my solution as well if for nothing else than a different perspective. – Eric Hodonsky Jun 16 '17 at 19:13
  • 2
    This is not really that clean in my mind. I would rather use an anchor tag honestly. Second, hitting the back button on the browser returns you the route that then redirects back to https://example.zendesk.com/hc/en-us/articles/123456789-Privacy-Policies – Jonathan Rys Sep 06 '17 at 19:12
  • 28
    For better back button behavior (verify for your application), use window.location.replace('http://example.com') – MattC Jul 17 '18 at 13:53
  • 1
    None of the answers do, the original post was asking about client redirects only, WHILE being aware that there is no 301 or 302 type true redirect support. – Eric Hodonsky Apr 07 '19 at 19:16
  • 5
    `window.location.href` is not optimal. If the user clicks the browser 'back' button after being redirected, she will get to the route that will immediately redirect her again. To avoid this, better use `window.location.replace()`. Source: https://stackoverflow.com/a/506004/163411 – targumon Dec 17 '20 at 14:51
  • This solution doesn't really take accessibility into account – bensampaio Sep 06 '21 at 08:46
  • This solution has absolutely nothing to do with the concept of pure components – ICW Oct 30 '21 at 22:10
166

With Link component of react-router you can do that. In the "to" prop you can specify 3 types of data:

  • a string: A string representation of the Link location, created by concatenating the location’s pathname, search, and hash properties.
  • an object: An object that can have any of the following properties:
    • pathname: A string representing the path to link to.
    • search: A string representation of query parameters.
    • hash: A hash to put in the URL, e.g. #a-hash.
    • state: State to persist to the location.
  • a function: A function to which current location is passed as an argument and which should return location representation as a string or as an object

For your example (external link):

https://example.zendesk.com/hc/en-us/articles/123456789-Privacy-Policies

You can do the following:

<Link to={{ pathname: "https://example.zendesk.com/hc/en-us/articles/123456789-Privacy-Policies" }} target="_blank" />

You can also pass props you’d like to be on the such as a title, id, className, etc.

Víctor Daniel
  • 1,985
  • 1
  • 13
  • 7
138

There isn’t any need to use the <Link /> component from React Router.

If you want to go to external link use an anchor tag.

<a target='_blank'
            rel='noopener noreferrer' href="https://meetflo.zendesk.com/hc/en-us/articles/230425728-Privacy-Policies">Policies</a>

Use the rel=”noopener” or rel=”noreferrer” link attributes for every link. The rel=”noreferrer” link attribute also functions the same as the “noopener” link attribute in that it prevents the linked site from taking control of the linking site.

Java bee
  • 2,522
  • 1
  • 12
  • 25
Diego Laciar
  • 2,898
  • 3
  • 14
  • 8
86

It doesn't need to request React Router. This action can be done natively and it is provided by the browser.

Just use window.location.

With React Hooks

const RedirectPage = () => {
  React.useEffect(() => {
    window.location.replace('https://www.google.com')
  }, [])
}

With React Class Component

class RedirectPage extends React.Component {
  componentDidMount(){
    window.location.replace('https://www.google.com')
  }
}

Also, if you want to open it in a new tab:

window.open('https://www.google.com', '_blank');
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Alan
  • 9,167
  • 4
  • 52
  • 70
52

I actually ended up building my own Component, <Redirect>. It takes information from the react-router element, so I can keep it in my routes. Such as:

<Route
  path="/privacy-policy"
  component={ Redirect }
  loc="https://meetflo.zendesk.com/hc/en-us/articles/230425728-Privacy-Policies"
  />

Here is my component in case anyone is curious:

import React, { Component } from "react";

export class Redirect extends Component {
  constructor( props ){
    super();
    this.state = { ...props };
  }
  componentWillMount(){
    window.location = this.state.route.loc;
  }
  render(){
    return (<section>Redirecting...</section>);
  }
}

export default Redirect;

Note: This is with react-router: 3.0.5, it is not so simple in 4.x

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Eric Hodonsky
  • 5,617
  • 4
  • 26
  • 36
  • you don't HAVE to do anything, react is a framework, and there is a lot of value in a framework. THIS is how to do it within the react framework. It DOES NOT however take into account the browser history module that could be wrapped in here to, making this even more useful. Also Please note "window.location" is how it was done in 1999. This is just a way to add it to your routes table for client side routing. It's not a "good" solution. – Eric Hodonsky Jul 03 '17 at 17:37
  • in react -router v4 you can use render instead component – Irrech Feb 22 '18 at 13:39
  • 4
    @Irrech "render instead component" means nothing. If you have an answer to the question please add it and give some detail of how you would implement. – Eric Hodonsky Feb 27 '18 at 17:16
  • 5
    @MuhammadUmer or you just use an anchor tag. react-router is pretty strictly meant for routing just within your application. you can disagree with that design decision (i know *i* do), but it's not "done better in 1999", it's just done the same. – worc Oct 02 '18 at 18:10
  • What if we want to pass the URL also dynamically along with HTTP Status code while redirecting to external site. I got some example, but its not clear with my requirement https://gist.github.com/arasmussen/f2c01dc858481590f6bffae6b540632c – Krishna Mani Sep 09 '20 at 15:11
9

Using some of the information here, I came up with the following component which you can use within your route declarations. It's compatible with React Router v4.

It's using TypeScript, but it should be fairly straightforward to convert to native JavaScript:

interface Props {
  exact?: boolean;
  link: string;
  path: string;
  sensitive?: boolean;
  strict?: boolean;
}

const ExternalRedirect: React.FC<Props> = (props: Props) => {
  const { link, ...routeProps } = props;

  return (
    <Route
      {...routeProps}
      render={() => {
        window.location.replace(props.link);
        return null;
      }}
    />
  );
};

And use with:

<ExternalRedirect
  exact={true}
  path={'/privacy-policy'}
  link={'https://example.zendesk.com/hc/en-us/articles/123456789-Privacy-Policies'}
/>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jens Bodal
  • 1,707
  • 1
  • 22
  • 32
8

I went through the same issue. I want my portfolio to redirect to social media handles. Earlier I used {Link} from "react-router-dom". That was redirecting to the sub directory as here,

enter image description here

Link can be used for routing web pages within a website. If we want to redirect to an external link then we should use an anchor tag. Like this,

enter image description here

Neel gorasiya
  • 155
  • 1
  • 8
  • 6
    Please use text, not pictures of text for code and any text-based information (like URLs). – Heretic Monkey May 22 '22 at 20:33
  • Please review *[Why not upload images of code/errors when asking a question?](https://meta.stackoverflow.com/questions/285551/)* (e.g., *"Images should only be used to illustrate problems that* ***can't be made clear in any other way,*** *such as to provide screenshots of a user interface."*) and [do the right thing](https://stackoverflow.com/posts/67528870/edit) (it covers answers as well). Thanks in advance. – Peter Mortensen Dec 13 '22 at 01:07
  • This doesn't actually redirect. This creates an HTML tag the needs to be clicked by the user in order for them to be redirected. – MickeyDickey Mar 21 '23 at 23:03
7

The simplest solution is to use a render function and change the window.location.

<Route path="/goToGoogle"
       render={() => window.location = "https://www.google.com"} />

If you want a small reusable component, you can just extract it like this:

const ExternalRedirect = ({ to, ...routeProps }) => {
   return <Route {...routeProps} render={() => window.location = to} />;
};

and then use it (e.g. in your router switch) like this:

<Switch>
    ...
    <ExternalRedirect exact path="/goToGoogle" to="https://www.google.com" />
</Switch>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
René Link
  • 48,224
  • 13
  • 108
  • 140
  • 1
    will the work? – Rohan Devaki Nov 17 '21 at 17:13
  • Is there a reason I don't know of why this is better than using the back button from the external destination for example? – Andy Jan 29 '22 at 23:22
  • Writing a component might help you some day. If the way you redirect should be changed you only need to change the `ExternalRedirect` component. E.g. you want to display a confirmation dialog before redirecting: "You will be redirected to ... Continue?" – René Link Jan 30 '22 at 09:59
6

I had luck with this:

<Route
    path="/example"
    component={() => {
        global.window && (global.window.location.href = 'https://example.com');
        return null;
    }}
/>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Alex Billson
  • 61
  • 1
  • 3
6

I solved this on my own (in my web application) by adding an anchor tag and not using anything from React Router, just a plain anchor tag with a link as you can see in the picture screenshot of using anchor tag in a React app without using React Router

Basically, you are not routing your user to another page inside your app, so you must not use the internal router, but use a normal anchor.

Although this is for a non-react-native solution, but you can try.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
CEBKUN
  • 61
  • 1
  • 4
5

In React Route V6 render props were removed. It should be a redirect component.

RedirectUrl:

const RedirectUrl = ({ url }) => {
  useEffect(() => {
    window.location.href = url;
  }, [url]);

  return <h5>Redirecting...</h5>;
};

Route:

<Routes>
   <Route path="/redirect" element={<RedirectUrl url="https://google.com" />} />
</Routes>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Okan Karadag
  • 2,542
  • 1
  • 11
  • 23
4

I think the best solution is to just use a plain old <a> tag. Everything else seems convoluted. React Router is designed for navigation within single page applications, so using it for anything else doesn't make a whole lot of sense. Making an entire component for something that is already built into the <a> tag seems... silly?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ICW
  • 4,875
  • 5
  • 27
  • 33
4

In React Router v6, component is unavailable. Instead, now it supports element. Make a component redirecting to the external site and add it as shown.

import * as React from 'react';
import { Routes, Route } from "react-router-dom";

function App() {
  return(
    <Routes>
      // Redirect
      <Route path="/external-link" element={<External />} />
    </Routes>
  );
}

function External() {
  window.location.href = 'https://google.com';
  return null;
}

export default App;
3

Complementing Víctor Daniel's answer here: Link's pathname will actually take you to an external link only when there's the 'https://' or 'http://' before the link.

You can do the following:

<Link to={{ pathname:
> "https://example.zendesk.com/hc/en-us/articles/123456789-Privacy-Policies"
> }} target="_blank" />

Or if your URL doesn't come with 'https://', I'd do something like:

<Link to={{pathname:`https://${link}`}} target="_blank" />

Otherwise it will prepend the current base path, as Lorenzo Demattécommented.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Carras
  • 41
  • 1
1

I don't think React Router provides this support. The documentation mentions

A < Redirect > sets up a redirect to another route in your application to maintain old URLs.

You could try using something like React-Redirect instead.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ytibrewala
  • 957
  • 1
  • 8
  • 12
1

To expand on Alan's answer, you can create a <Route/> that redirects all <Link/>'s with "to" attributes containing 'http:' or 'https:' to the correct external resource.

Below is a working example of this which can be placed directly into your <Router>.

<Route path={['/http:', '/https:']} component={props => {
  window.location.replace(props.location.pathname.substr(1)) // substr(1) removes the preceding '/'
  return null
}}/>
Sam Mckay
  • 71
  • 3
1

I was facing the same issue and solved it using by http:// or https:// in React.

Like as: <a target="_blank" href="http://www.example.com/" title="example">See detail</a>

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
0

For V3, although it may work for V4. Going off of Eric's answer, I needed to do a little more, like handle local development where 'http' is not present on the URL. I'm also redirecting to another application on the same server.

Added to the router file:

import RedirectOnServer from './components/RedirectOnServer';

<Route path="/somelocalpath"
       component={RedirectOnServer}
       target="/someexternaltargetstring like cnn.com"
/>

And the Component:

import React, { Component } from "react";

export class RedirectOnServer extends Component {

  constructor(props) {
    super();
    // If the prefix is http or https, we add nothing
    let prefix = window.location.host.startsWith("http") ? "" : "http://";
    // Using host here, as I'm redirecting to another location on the same host
    this.target = prefix + window.location.host + props.route.target;
  }
  componentDidMount() {
    window.location.replace(this.target);
  }
  render(){
    return (
      <div>
        <br />
        <span>Redirecting to {this.target}</span>
      </div>
    );
  }
}

export default RedirectOnServer;
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
MattC
  • 5,874
  • 1
  • 47
  • 40
0

You can use for your dynamic URL:

<Link to={{pathname:`${link}`}}>View</Link>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Dr Venom
  • 25
  • 2
0

I am offering an answer relevant to React Router v6 to handle dynamic routing.

I created a generic component called redirect:

export default function Redirect(params) {
  window.location.replace('<Destination URL>' + "/." params.destination);

  return (
    <div />

  )
}

I then called it in my router file:

<Route path='/wheretogo' element={<Redirect destination="wheretogo"/>}/>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ahmed Haque
  • 7,174
  • 6
  • 26
  • 33
0

Save this html page on your disk with the name ExampleLinkReact.html,

and open it with your browser, say chromium 115.

<!DOCTYPE html>
<html>
  <head>
    <meta charset='UTF-8'>
    <title>ExampleLinkReact</title>
    <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
    <script src='https://unpkg.com/react-router-dom@5.0.0/umd/react-router-dom.min.js'></script>
    <script src='https://unpkg.com/babel-standalone@6.26.0/babel.js'></script>
    

  </head>
  <body>
    <div id='root'></div>
    <script type='text/babel'>
      const Link = ReactRouterDOM.Link;
      const Route = ReactRouterDOM.Route;

      const ExampleLinkReact = () => (
      
<div style={removeallstyles}> {/*1*/}
 <div style={container100postlist}>         
    
    <p style={style_label}> ExampleLinkReact </p>
    <div style={hspace3}> </div>
    <p> Open every link in new tab</p>

    
  <div style={block1}>  
  <ReactRouterDOM.HashRouter>
     <ul style={ulist_style}>
      <li><Link to="/InnerComponent">InnerComponent</Link></li>
      <li><Link to='/LocalHTMLPage'>LocalHTMLPage</Link></li>
      <li><Link to='/LinkExternalUrl'>LinkExternalUrl</Link></li>
    </ul>


    
    <Route path="/InnerComponent" exact component={InnerComponent} />
    <Route exact path="/LocalHTMLPage" render={() => {window.location.href="LocalHTMLPage.html"}} />
    <Route exact path="/LinkExternalUrl" render={() => {window.location.href="https://example.com/1234"}} />
  </ReactRouterDOM.HashRouter>
    
    
    
    <div style={hspace3}> </div>
  </div> {/*block1 end*/}

  {/*/////////////////////////////////////////////////////////////////////////////////////*/}
  {/*/////////////////////////////////////////////////////////////////////////////////////*/}
    

    
    </div> {/*container100postlist*/}
</div> /*removeallstyles*/
      )

      
      //define InnerComponent
      const InnerComponent = () => <h1>InnerComponent</h1>

      
      
/////////////////////////////////////////////////////////////////////////////////// 
 {/*CSS CODE START. */}
 //This is only elementary css, you can ignore it;

 const removeallstyles = { all: 'revert',}
 const hspace3={height: 0.05*window.innerHeight, backgroundColor: 'transparent', position: 'relative'}; 
 const vhspace1={width: 0.05*window.innerWidth, backgroundColor: 'transparent', position: 'inline-block'};  
 
 
 
    
 
 
 //container100postlist     
 const container100postlist_width =94;
 const container100postlist_border=1;   
 const container100postlist  =
 {
    //margin:'0 auto',    
    //textAlign: 'center',
    position: 'absolute',
    width: container100postlist_width+'vw',
    backgroundColor:'transparent',  
    display: 'block',
    clear: 'both',
 };

 
 
 
 const style_label =
 {
    backgroundColor:'transparent',  
    marginTop: '1vh',
    marginBottom: '1vh',
    textAlign: 'left',
    display: 'block',
    clear: 'both',
    position: 'relative',
    fontWeight: 'bold',   
 };
 
 
    

 var block1 =
  {
    textAlign: 'left',
    float: 'left',
    display: 'block',
    clear: 'both',
    padding: '0.5vw',
    //height: '40%',
    width: '97vw',
    //backgroundColor:'red',    
    border: '0.1vh solid red',    
  };



  
 const ulist_style =
 {
    //listStyle: 'none',
    listStylePosition: 'inside',
    paddingLeft: '1vw',
 }



 {/*CSS CODE END. */}


/////////////////////////////////////////////////////////////////////////////////// 
      
      
      
      ReactDOM.render(<ExampleLinkReact />, document.querySelector('#root'));
    </script>
  </body>
</html> 

quine9997
  • 685
  • 7
  • 13
-1

Using React with TypeScript, you get an error as the function must return a React element, not void. So I did it this way using the Route render method (and using React router v4):

redirectToHomePage = (): null => {
    window.location.reload();
    return null;
};

<Route exact path={'/'} render={this.redirectToHomePage} />

Where you could instead also use window.location.assign(), window.location.replace(), etc.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
chezwhite
  • 700
  • 7
  • 8
-1
import React from "react";
import { BrowserRouter as Router, Route } from "react-router-dom";

function App() {
  return (
    <Router>
      <Route path="/" exact>
        {window.location.replace("http://agrosys.in")}
      </Route>
    </Router>
  );
}

export default App;
Arnav Singh
  • 194
  • 2
  • 4
-2

If you are using server-side rending, you can use StaticRouter. With your context as props and then adding <Redirect path="/somewhere" /> component in your app. The idea is every time React Router matches a redirect component it will add something into the context you passed into the static router to let you know your path matches a redirect component.

Now that you know you hit a redirect you just need to check if that’s the redirect you are looking for. then just redirect through the server. ctx.redirect('https://example/com').

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Rei Dien
  • 554
  • 2
  • 12
  • I'm asking for a way to do it in the client. It actually should be done at the DNS level if done correctly. Second would be in the initial server request. Since I'm hosting on S3, there is no server-side. SO I'm stuck for now until our dev-ops guy can do the redirect at the Service Level. – Eric Hodonsky Mar 23 '17 at 22:34
  • what you can do is, `` – Rei Dien Mar 23 '17 at 22:39
-4

You can now link to an external site using React Link by providing an object to to with the pathname key:

<Link to={ { pathname: '//example.zendesk.com/hc/en-us/articles/123456789-Privacy-Policies' } } >

If you find that you need to use JavaScript to generate the link in a callback, you can use window.location.replace() or window.location.assign().

Over using window.location.replace(), as other good answers suggest, try using window.location.assign().

window.location.replace() will replace the location history without preserving the current page.

window.location.assign() will transition to the URL specified, but will save the previous page in the browser history, allowing proper back-button functionality.

location.replace()

location.assign()

Also, if you are using a window.location = url method as mentioned in other answers, I highly suggest switching to window.location.href = url.

There is a heavy argument about it, where many users seem to adamantly want to revert the newer object type window.location to its original implementation as string merely because they can (and they egregiously attack anyone who says otherwise), but you could theoretically interrupt other library functionality accessing the window.location object.

Check out this conversation. It's terrible. JavaScript: Setting location.href versus location

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
WebWanderer
  • 10,380
  • 3
  • 32
  • 51
-5

I was able to achieve a redirect in react-router-dom using the following

<Route exact path="/" component={() => <Redirect to={{ pathname: '/YourRoute' }} />} />

For my case, I was looking for a way to redirect users whenever they visit the root URL http://myapp.com to somewhere else within the app http://myapp.com/newplace. so the above helped.

walecloud
  • 306
  • 3
  • 5
  • 3
    The OP clearly states that he's trying to redirect to an external resource, not to a route inside the same app. – Neets Mar 14 '19 at 17:00
  • Clearly, I was specific about my use case and dropped that if he could apply it to his. my solution says within my app, he could use that as an example. – walecloud Mar 19 '19 at 03:11
  • 2
    If you want to showcase your use case to people, please write a blog about it. Stackoverflow is for answering the query that people have, not your use-case. Also, the right way to implement your use case is - – Abhas Aug 05 '20 at 21:16
  • I found this very helpful in understanding that react-routers ` – Devin Rhode Jul 14 '21 at 16:58