Łącze zewnętrzne React-Router

114

Ponieważ używam routera React do obsługi tras w aplikacji Reaguj, jestem ciekaw, czy istnieje sposób na przekierowanie do zasobu zewnętrznego.

Powiedz, że ktoś uderza:

example.com/privacy-policy

Chciałbym przekierować do:

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

Znajduję dokładnie zero pomocy w unikaniu pisania tego w zwykłym JS na moim index.html ładującym się za pomocą czegoś takiego:

if ( window.location.path === "privacy-policy" ){
  window.location = "example.zendesk.com/hc/en-us/articles/123456789-Privacy-Policies"
}
Eric Hodonsky
źródło
Którego routera React używasz?
Tyler McGinnis
Używam wersji 3.x
Eric Hodonsky
1
Po prostu zmień, window.location.hrefaby mieć formalne przekierowanie.
Amirhossein Mehrvarzi
2
@AmirhosseinMehrvarzi to właściwie nic nie znaczy. Czy mógłbyś być bardziej szczegółowy lub podać przykład? Nie jestem też pewien, czy zauważyłeś, ale to pytanie ma już zaakceptowaną odpowiedź dotyczącą routera React & React, o co chodzi w tym pytaniu.
Eric Hodonsky
1
@Relic Musisz użyć tego jako adresu URL w swoim warunku if. Miałem podobny problem kilka dni temu i uznałem ten sposób za prosty i skuteczny. Przekierowuje natychmiast. Zaakceptowaną odpowiedzią jest rozwiązanie routingu (chociaż narusza zasady trasy, biorąc pod uwagę, że architektura trasy służy do nawigacji wewnątrz aplikacji, a nie na zewnątrz), które nie działa w żadnym środowisku takim jak moje
Amirhossein Mehrvarzi

Odpowiedzi:

170

Oto jedna linijka dotycząca używania React Router do przekierowania do łącza zewnętrznego:

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

Wykorzystuje koncepcję czystego komponentu React, aby zredukować kod komponentu do pojedynczej funkcji, która zamiast renderować cokolwiek, przekierowuje przeglądarkę do zewnętrznego adresu URL.

Działa zarówno na React Router 3, jak i 4.

Evgeny Lukianchikov
źródło
2
To działa, ale szukałem bardziej eleganckiego, skalowalnego rozwiązania. Zobacz, co wymyśliłem, ponieważ pozwoliło mi to pójść jeszcze dalej z przekierowaniami dla aplikacji mobilnych itp. (Nie ReactNative, prawdziwie natywne aplikacje). To, co robię, nie jest właściwym sposobem rozwiązania mojego problemu, ale sugeruję, abyś zbadał również moje rozwiązanie, choćby z innej perspektywy.
Eric Hodonsky
1
To naprawdę nie jest takie czyste w mojej głowie. Wolałbym uczciwie użyć tagu kotwicy. Po drugie, naciśnięcie przycisku Wstecz w przeglądarce zwraca trasę, która następnie przekierowuje z powrotem do example.zendesk.com/hc/en-us/articles/ ...
Jonathan Rys
11
Aby uzyskać lepsze zachowanie przycisku Wstecz (zweryfikuj swoją aplikację), użyj window.location.replace („ example.com” )
MattC
1
Żadna z odpowiedzi nie odpowiada, oryginalny post pytał tylko o przekierowania klientów, mając świadomość, że nie ma prawdziwej obsługi przekierowań typu 301 lub 302.
Eric Hodonsky
51

Nie ma potrzeby używania <Link />komponentu z routera reaktywnego.

Jeśli chcesz przejść do linku zewnętrznego, użyj tagu kotwicy.

<a target="_blank" href="https://meetflo.zendesk.com/hc/en-us/articles/230425728-Privacy-Policies">Policies</a>
Diego Laciar
źródło
20
OP pytał, jak to zrobić programowo, a nie deklaratywnie
Eric Hodonsky
13
Niepowiązana i myląca odpowiedź.
Priya Ranjan Singh
1
Jeśli to zrobisz, dodaj rel="noopener noreferrer"do<a>
S ..
5
Dobra odpowiedź, nie każdemu będzie to zależało tak długo, jak długo będzie działać.
FrankByte.com
39

Skończyło się na zbudowaniu własnego komponentu. <Redirect> Pobiera informacje z react-routerelementu, więc mogę je przechowywać w moich trasach. Jak na przykład:

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

Oto mój komponent na wypadek, gdyby ktoś był ciekawy:

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;

EDYCJA - UWAGA: To jest z react-router: 3.0.5, to nie jest takie proste w 4.x

Eric Hodonsky
źródło
nie MUSISZ nic robić, reagujesz to framework, a framework ma dużą wartość. Tak to się robi w ramach reagowania. NIE bierze jednak pod uwagę modułu historii przeglądarki, który można by zawinąć tutaj, co czyni go jeszcze bardziej użytecznym. Zwróć również uwagę, że "window.location" to sposób, w jaki to było zrobione w 1999 roku. Jest to tylko sposób na dodanie go do tabeli tras dla routingu po stronie klienta. To nie jest „dobre” rozwiązanie.
Eric Hodonsky
w React -router v4 możesz użyć komponentu renderowania
Irrech
3
@Irrech „renderuj zamiast komponentu” nic nie znaczy. Jeśli masz odpowiedź na pytanie, dodaj ją i opisz szczegółowo, jak byś ją wdrożył.
Eric Hodonsky
3
@MuhammadUmer lub po prostu użyj tagu kotwicy. reakcja-router jest dość ściśle przeznaczona do routingu tylko w Twojej aplikacji. można nie zgodzić się z tej decyzji projektowej (wiem, że nie), ale nie jest to „zrobić lepiej w 1999 roku”, to po prostu zrobić to samo.
worc
21

Nie ma potrzeby żądania odpowiedzi routera. Tę czynność można wykonać natywnie i zapewnia ją przeglądarka.

po prostu użyj window.location

class RedirectPage extends React.Component {
  componentDidMount(){
    window.location.replace('http://www.google.com')
  }
}
Alan
źródło
1
Ta odpowiedź jest niekompletna, nie pozwala na abstrakcję lub jest powiązana z routerem
Eric Hodonsky
8
To jest cel. Nie ma potrzeby żądania odpowiedzi routera. Tę czynność można wykonać natywnie i zapewnia ją przeglądarka.
Alan
10

Z komponentem Link w React-router możesz to zrobić. W właściwości „ do ” możesz określić 3 typy danych:

  • ciąg : ciąg znaków reprezentujący położenie łącza, utworzony przez konkatenację nazwy ścieżki, wyszukiwania i właściwości skrótu lokalizacji.
  • obiekt : obiekt, który może mieć dowolną z następujących właściwości:
    • pathname : ciąg reprezentujący ścieżkę do połączenia.
    • search : ciąg znaków reprezentujący parametry zapytania.
    • hash : hash do umieszczenia w adresie URL, np. # a-hash.
    • stan : stan, aby zachować lokalizację.
  • a function : funkcja, do której bieżące położenie jest przekazywane jako argument i która powinna zwrócić reprezentację położenia w postaci ciągu lub obiektu

Na przykład (link zewnętrzny):

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

Możesz wykonać następujące czynności:

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

Możesz również przekazywać rekwizyty, na których chcesz się znaleźć, takie jak tytuł, identyfikator, nazwa klasy itp.

Víctor Daniel
źródło
1
To najprostsze rozwiązanie i działa dobrze.
hPNJ7MHTyg
5

Korzystając z niektórych informacji tutaj, wymyśliłem następujący komponent, którego możesz użyć w deklaracjach tras. Jest kompatybilny z React Router v4.

Używa maszynopisu, ale konwersja do natywnego javascript powinna być dość prosta:

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

I używaj z:

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

Miałem szczęście z tym:

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

Myślę, że React-Router nie zapewnia takiej obsługi. Dokumentacja wspomina

<Redirect> ustawia przekierowanie do innej trasy w Twojej aplikacji, aby zachować stare adresy URL.

Można spróbować użyć czegoś podobnego React przekierowanie zamiast

ytibrewala
źródło
1

Aby rozwinąć odpowiedź Alana, możesz utworzyć <Route/>przekierowanie wszystkich<Link/> z atrybutami „do” zawierającymi „http:” lub „https:” do właściwego zasobu zewnętrznego.

Poniżej znajduje się działający przykład, który można umieścić bezpośrednio w pliku <Router>.

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

DLA V3, chociaż może działać dla V4. Wychodząc od odpowiedzi Erica, musiałem zrobić trochę więcej, na przykład zająć się rozwojem lokalnym, gdzie „http” nie występuje w adresie URL. Przekierowuję również do innej aplikacji na tym samym serwerze.

Dodano do pliku routera:

import RedirectOnServer from './components/RedirectOnServer';

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

A komponent:

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
źródło
-1

Używając Reacta z Typescript, otrzymujesz błąd, ponieważ funkcja musi zwrócić element reakcji, a nie void. Zrobiłem to w ten sposób, używając metody renderowania trasy (i używając routera React v4):

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

Gdzie można również użyć zamiast window.location.assign(), window.location.replace()etc

chezwhite
źródło
-2

Jeśli używasz renderowania po stronie serwera, możesz użyć StaticRouter. Za pomocą swojego contextas, propsa następnie dodając <Redirect path="/somewhere" />komponent do swojej aplikacji. Chodzi o to, że za każdym razem, gdy reakcja-router dopasuje komponent przekierowania, doda coś do kontekstu przekazanego do routera statycznego, aby poinformować cię, że twoja ścieżka pasuje do komponentu przekierowania. teraz, gdy wiesz, że trafiłeś w przekierowanie, wystarczy sprawdzić, czy to przekierowanie, którego szukasz. następnie po prostu przekieruj przez serwer. ctx.redirect('https://example/com').

Rei Dien
źródło
Proszę o sposób na zrobienie tego w kliencie. W rzeczywistości należy to zrobić na poziomie DNS, jeśli zostanie wykonane poprawnie. Drugi byłby w początkowym żądaniu serwera. Ponieważ hostuję na S3, nie ma po stronie serwera. Więc na razie utknąłem, dopóki nasz facet od deweloperów nie będzie mógł wykonać przekierowania na poziomie usługi.
Eric Hodonsky
co możesz zrobić,<Redirect push={ true } to="/pathtoredirect" />
Rei Dien
-4

Udało mi się uzyskać przekierowanie w React-router-dom za pomocą następującego

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

W moim przypadku szukałem sposobu na przekierowanie użytkowników za każdym razem, gdy odwiedzają główny adres URL http://myapp.comdo innego miejsca w aplikacji http://myapp.com/newplace. więc powyższe pomogło.

walecloud
źródło
2
OP wyraźnie stwierdza, że ​​próbuje przekierować do zasobu zewnętrznego, a nie do trasy w tej samej aplikacji.
Neets,
Najwyraźniej sprecyzowałem mój przypadek użycia i porzuciłem to, gdyby mógł zastosować to do swojego. moje rozwiązanie mówi w mojej aplikacji, mógłby użyć tego jako przykładu.
walecloud
1
Jeśli chcesz pokazać ludziom swój przypadek użycia, napisz o tym blog. Stackoverflow służy do odpowiadania na zapytania, które mają ludzie, a nie do twojego przypadku użycia. Prawidłowy sposób na zaimplementowanie tego przypadku to - <Redirect from = "/" to = {{pathname: '/ YourRoute'}} />
Abhas