Link externo do React-Router

113

Como estou usando o react-router para lidar com minhas rotas em um app react, estou curioso para saber se há uma maneira de redirecionar para um recurso externo.

Digamos que alguém acerte:

example.com/privacy-policy

Eu gostaria que redirecionasse para:

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

Não estou encontrando nenhuma ajuda para evitar escrevê-lo em JS simples em meu carregamento de index.html com algo como:

if ( window.location.path === "privacy-policy" ){
  window.location = "example.zendesk.com/hc/en-us/articles/123456789-Privacy-Policies"
}
Eric Hodonsky
fonte
Qual roteador React você está usando?
Tyler McGinnis de
Estou usando a versão 3.x
Eric Hodonsky
1
Simplesmente mude window.location.hrefpara ter um redirecionamento formal.
Amirhossein Mehrvarzi
2
@AmirhosseinMehrvarzi isso não significa nada. Você poderia ser mais específico ou dar um exemplo? Além disso, não tenho certeza se você percebeu, mas esta pergunta já tem uma resposta aceita sobre o React & React Router, que é o assunto da pergunta.
Eric Hodonsky
1
@Relic Você precisa usar isso como seu url em sua condição if. Tive um problema semelhante há alguns dias e achei essa maneira simples e eficaz. Ele redireciona imediatamente. A resposta aceita é uma solução de roteamento (embora viole os princípios da rota, considerando que a arquitetura da rota é para navegação dentro do aplicativo e não para fora) que não funciona para nenhum ambiente como o meu
Amirhossein Mehrvarzi

Respostas:

170

Aqui está uma linha para usar o React Router para redirecionar para um link externo:

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

Ele usa o conceito de componente puro React para reduzir o código do componente a uma única função que, em vez de renderizar qualquer coisa, redireciona o navegador para uma URL externa.

Funciona nos roteadores React 3 e 4.

Evgeny Lukianchikov
fonte
2
Isso funciona, mas eu estava procurando uma solução escalável mais elegante. Veja o que eu descobri, pois me permitiu ir ainda mais longe com redirecionamentos para MobileApps etc (Not ReactNative, aplicativos verdadeiramente nativos). Agora, o que estou fazendo não é a maneira certa de resolver meu problema, mas para resolver esse problema, sugiro que você investigue minha solução também, senão por uma perspectiva diferente.
Eric Hodonsky
1
Isso não está muito claro em minha mente. Eu prefiro usar uma etiqueta de âncora honestamente. Em segundo lugar, apertar o botão Voltar do navegador retorna a rota que redireciona de volta para example.zendesk.com/hc/en-us/articles/…
Jonathan Rys
11
Para um melhor comportamento do botão Voltar (verifique para seu aplicativo), use window.location.replace (' example.com' )
MattC
1
Nenhuma das respostas responde, a postagem original estava perguntando sobre redirecionamentos de cliente apenas, embora esteja ciente de que não há suporte para redirecionamento verdadeiro do tipo 301 ou 302.
Eric Hodonsky,
50

Não há necessidade de usar o <Link />componente do roteador react.

Se você quiser ir para um link externo, use uma tag âncora.

<a target="_blank" href="https://meetflo.zendesk.com/hc/en-us/articles/230425728-Privacy-Policies">Policies</a>
Diego laciar
fonte
20
O OP estava perguntando como fazer isso de forma programática, não declarativa
Eric Hodonsky,
13
Resposta não relacionada e enganosa.
Priya Ranjan Singh
1
Se você usar isso, adicione rel="noopener noreferrer"ao<a>
S ..
5
Boa resposta, nem todo mundo vai se importar, contanto que faça funcionar.
FrankByte.com
39

Na verdade, acabei construindo meu próprio componente. <Redirect> Ele obtém informações do react-routerelemento para que eu possa mantê-lo em minhas rotas. Tal como:

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

Aqui está meu componente no caso - qualquer um está curioso:

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;

EDITAR - NOTA: Isto é com react-router: 3.0.5, não é tão simples no 4.x

Eric Hodonsky
fonte
você não PRECISA fazer nada, reagir é uma estrutura e há muito valor em uma estrutura. ISTO é como fazer dentro da estrutura de reação. No entanto, NÃO leva em consideração o módulo de histórico do navegador que pode ser agrupado aqui, tornando-o ainda mais útil. Observe também que "window.location" é como era feito em 1999. Esta é apenas uma maneira de adicioná-lo à sua tabela de rotas para roteamento do lado do cliente. Não é uma solução "boa".
Eric Hodonsky
no react -router v4 você pode usar render em vez do componente
Irrech
3
@Irrech "renderizar ao invés de componente" não significa nada. Se você tiver uma resposta para a pergunta, adicione-a e dê alguns detalhes de como você a implementaria.
Eric Hodonsky
3
@MuhammadUmer ou você apenas usa uma tag âncora. react-router destina-se estritamente ao roteamento apenas dentro de seu aplicativo. você pode discordar dessa decisão de design (eu sei que sim), mas não foi "feito melhor em 1999", apenas foi feito da mesma forma.
worc
21

Não é necessário solicitar o roteador de reação. Esta ação pode ser feita nativamente e é fornecida pelo navegador.

Apenas use window.location

class RedirectPage extends React.Component {
  componentDidMount(){
    window.location.replace('http://www.google.com')
  }
}
Alan
fonte
1
Esta resposta está incompleta, não permite abstração ou está relacionada ao roteador
Eric Hodonsky
8
Esse é o objetivo. Não é necessário solicitar o roteador de reação. Esta ação pode ser feita nativamente e é fornecida pelo navegador.
Alan
10

Com o componente Link do react-router, você pode fazer isso. Na proposta " para ", você pode especificar 3 tipos de dados:

  • uma string : uma representação de string do local do Link, criada pela concatenação do nome do caminho, pesquisa e propriedades hash do local.
  • um objeto : um objeto que pode ter qualquer uma das seguintes propriedades:
    • pathname : uma string que representa o caminho para o link.
    • pesquisa : uma representação de string de parâmetros de consulta.
    • hash : Um hash para inserir na URL, por exemplo, # a-hash.
    • estado : estado para persistir no local.
  • uma função : uma função para a qual a localização atual é passada como um argumento e que deve retornar a representação da localização como uma string ou como um objeto

Para o seu exemplo (link externo):

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

Você pode fazer o seguinte:

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

Você também pode passar adereços que gostaria que fossem, como título, id, className, etc.

Víctor Daniel
fonte
1
Esta é a solução mais simples e funciona bem.
hPNJ7MHTyg
5

Usando algumas das informações aqui, eu vim com o seguinte componente que você pode usar em suas declarações de rota. É compatível com React Router v4.

Ele está usando o texto digitado, mas deve ser bastante simples para converter para javascript nativo:

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;
      }}
    />
  );
};

E use com:

<ExternalRedirect
  exact={true}
  path={'/privacy-policy'}
  link={'https://example.zendesk.com/hc/en-us/articles/123456789-Privacy-Policies'}
/>
Jens Bodal
fonte
2

Tive sorte com isso:

  <Route
    path="/example"
    component={() => {
    global.window && (global.window.location.href = 'https://example.com');
    return null;
    }}
/>
Alex Billson
fonte
1

Não acho que o React-Router forneça esse suporte. A documentação menciona

Um <Redirecionamento> configura um redirecionamento para outra rota em seu aplicativo para manter URLs antigos.

Você pode tentar usar algo como Reagir-Redirect vez

ytibrewala
fonte
1

Para expandir a resposta de Alan, você pode criar um <Route/>que redirecione todos <Link/>os atributos com "para" contendo 'http:' ou 'https:' para o recurso externo correto.

Abaixo está um exemplo prático disso, que pode ser colocado diretamente em seu <Router>.

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

PARA V3, embora possa funcionar para V4. Saindo da resposta de Eric, eu precisava fazer um pouco mais, como lidar com o desenvolvimento local onde 'http' não está presente na url. Também estou redirecionando para outro aplicativo no mesmo servidor.

Adicionado ao arquivo do roteador:

import RedirectOnServer from './components/RedirectOnServer';

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

E o componente:

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;
MattC
fonte
-1

Usando React com Typescript, você obtém um erro porque a função deve retornar um elemento react, não void. Então, fiz dessa maneira usando o método de renderização de rota (e usando o roteador React v4):

redirectToHomePage = (): null => {
    window.location.reload();
    return null;
  };    
<Route exact path={'/'} render={this.redirectToHomePage} />

Onde você também pode usar window.location.assign(), window.location.replace()etc.

chezwhite
fonte
-2

Se você estiver usando a conversão do lado do servidor, você pode usar StaticRouter. Com o contextAS propse, em seguida, adicionando o <Redirect path="/somewhere" />componente ao seu aplicativo. A ideia é que toda vez que react-router corresponder a um componente de redirecionamento, ele adicionará algo ao contexto que você passou para o roteador estático para que saiba que seu caminho corresponde a um componente de redirecionamento. agora que você sabe que atingiu um redirecionamento, só precisa verificar se esse é o redirecionamento que você está procurando. em seguida, basta redirecionar através do servidor. ctx.redirect('https://example/com').

Rei Dien
fonte
Estou pedindo uma maneira de fazer no cliente. Na verdade, deve ser feito no nível DNS, se feito corretamente. O segundo seria na solicitação inicial do servidor. Como estou hospedando no S3, não há servidor. POR ISSO, estou preso por enquanto até que nosso cara de dev-ops possa fazer o redirecionamento no nível de serviço.
Eric Hodonsky
o que você pode fazer é,<Redirect push={ true } to="/pathtoredirect" />
Rei Dien
-4

Consegui um redirecionamento no react-router-dom usando o seguinte

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

No meu caso, eu estava procurando uma maneira de redirecionar os usuários sempre que eles visitarem o URL raiz http://myapp.compara algum outro lugar dentro do aplicativo http://myapp.com/newplace. então o acima ajudou.

Walecloud
fonte
2
O OP afirma claramente que ele está tentando redirecionar para um recurso externo, não para uma rota dentro do mesmo aplicativo.
Neets de
Claramente, fui específico sobre meu caso de uso e abandonei isso se ele pudesse aplicá-lo ao dele. minha solução diz dentro do meu aplicativo, ele poderia usar isso como exemplo.
walecloud
1
Se você quiser mostrar seu caso de uso para as pessoas, escreva um blog sobre ele. Stackoverflow serve para responder à consulta das pessoas, não ao seu caso de uso. Além disso, a maneira certa de implementar seu caso de uso é - <Redirect from = "/" to = {{pathname: '/ YourRoute'}} />
Abhas