Nawiguj programowo, używając routera reagującego V4


336

Właśnie wymieniłem react-routerz v3 na v4.
Ale nie jestem pewien, jak programowo nawigować w funkcji członka Component. tzn. w handleClick()funkcji chcę nawigować /path/some/wherepo przetworzeniu niektórych danych. Robiłem to przez:

import { browserHistory } from 'react-router'
browserHistory.push('/path/some/where')

Ale nie mogę znaleźć takich interfejsów w wersji 4.
Jak nawigować za pomocą v4?


3
Możesz uzyskać dostęp do obiektu historii w wersji 4 za pomocą rekwizytów: this.props.history.push ('/')
colemerrick

6
Co jeśli chcesz uzyskać do niego dostęp z innego miejsca niż Component? Na przykład wewnątrz akcji redux.
Maximus S

73
czasami zastanawiam się, dlaczego tak skomplikowane jest po prostu przejście z jednego linku do drugiego =))
Thai Tran

12
Można by pomyśleć, że w dzisiejszych czasach przekierowanie nie byłoby tak skomplikowane.
JohnAllen

Odpowiedzi:


414

Jeśli celujesz w środowiska przeglądarki, musisz użyć react-router-dompakietu zamiast react-router. Stosują to samo podejście, co React, aby oddzielić rdzeń ( react) i kod specyficzny dla platformy, ( react-dom, react-native) z tą niewielką różnicą, że nie trzeba instalować dwóch oddzielnych pakietów, więc pakiety środowiska zawierają wszystko potrzebujesz. Możesz dodać go do swojego projektu jako:

yarn add react-router-dom

lub

npm i react-router-dom

Pierwszą rzeczą, którą musisz zrobić, to podać <BrowserRouter>jako najwyższy komponent nadrzędny w swojej aplikacji. <BrowserRouter>używa historyinterfejsu API HTML5 i zarządza nim za Ciebie, więc nie musisz się martwić o samodzielne tworzenie instancji i przekazywanie jej do <BrowserRouter>komponentu jako rekwizytu (tak jak to robiłeś w poprzednich wersjach).

W wersji 4 do nawigowania programowego potrzebujesz dostępu do historyobiektu, który jest dostępny przez React context, pod warunkiem, że masz komponent <BrowserRouter> dostawcy jako najwyższy nadrzędny w twojej aplikacji. Biblioteka udostępnia poprzez kontekst routerobiekt, który sam zawiera historyjako właściwość. historyInterfejs oferuje kilka metod nawigacji, takie jakpush , replacei goBack, między innymi. Można sprawdzić całą listę właściwości i metody tutaj .

Ważna uwaga dla użytkowników Redux / Mobx

Jeśli używasz w aplikacji aplikacji redux lub mobx, być może natrafiłeś na problemy z komponentami, które powinny rozpoznawać lokalizację, ale nie są renderowane ponownie po uruchomieniu aktualizacji adresu URL

Dzieje się tak, ponieważ react-router przechodzi locationdo komponentów przy użyciu modelu kontekstowego.

Zarówno connect, jak i obserwator tworzą komponenty, których metody shouldComponentUpdate wykonują płytkie porównanie swoich bieżących rekwizytów i następnych rekwizytów. Te komponenty zostaną zrenderowane tylko, gdy zmieni się co najmniej jeden rekwizyt. Oznacza to, że w celu zapewnienia ich aktualizacji, gdy zmienia się lokalizacja, będą musieli otrzymać rekwizyt, który zmienia się, gdy zmienia się lokalizacja.

Dwa podejścia do rozwiązania tego:

  • Zawiń podłączony komponent w ścieżkę bez ścieżki <Route />. Obecnylocation obiekt jest jednym z rekwizytów <Route>przekazywanych do renderowanego komponentu
  • Owiń podłączony komponent komponentem withRouterwyższego rzędu, który w rzeczywistości ma ten sam efekt i wstrzykujelocation jak rekwizyt

Poza tym istnieją cztery sposoby programowej nawigacji, uporządkowane według zaleceń:

1.- Korzystanie z <Route> komponentu

Promuje deklaratywny styl. Przed wersją v4 <Route />komponenty były umieszczane na szczycie hierarchii komponentów, dlatego należy wcześniej pomyśleć o strukturze tras. Jednak teraz możesz mieć <Route>komponenty w dowolnym miejscu w drzewie, co pozwala na dokładniejszą kontrolę warunkowego renderowania w zależności od adresu URL. Routewstrzykuje match, locationa historyjako rekwizyty do swojego komponentu. Metody nawigacji (takie jak push,replace , goBack...) są dostępne jako właściwości historyobiektu.

Istnieją 3 sposoby renderowania czegoś Routeza pomocą albo component, renderalbo childrenrekwizytów, ale nie używaj więcej niż jednego w tym samym Route. Wybór zależy od przypadku użycia, ale w zasadzie dwie pierwsze opcje renderują komponent tylko wtedy, gdy pathpasuje do lokalizacji childrenadresu URL , natomiast w przypadku komponentu będzie renderowany, czy ścieżka pasuje do lokalizacji, czy nie (przydatne w dostosowywaniu interfejsu użytkownika na podstawie adresu URL pasujący).

Jeśli chcesz, aby dostosować moc renderowania komponentu , należy owinąć komponent w funkcji i użyć renderopcji, aby przejść do komponentu innych rekwizytów pragnienie, oprócz match, locationi history. Przykład ilustrujący:

import { BrowserRouter as Router } from 'react-router-dom'

const ButtonToNavigate = ({ title, history }) => (
  <button
    type="button"
    onClick={() => history.push('/my-new-location')}
  >
    {title}
  </button>
);

const SomeComponent = () => (
  <Route path="/" render={(props) => <ButtonToNavigate {...props} title="Navigate elsewhere" />} />
)    

const App = () => (
  <Router>
    <SomeComponent /> // Notice how in v4 we can have any other component interleaved
    <AnotherComponent />
  </Router>
);

2.- Korzystanie z withRouterHoC

Ten komponent wyższego rzędu wstrzykuje te same rekwizyty co Route. Jednak niesie ze sobą ograniczenie, że możesz mieć tylko 1 HoC na plik.

import { withRouter } from 'react-router-dom'

const ButtonToNavigate = ({ history }) => (
  <button
    type="button"
    onClick={() => history.push('/my-new-location')}
  >
    Navigate
  </button>
);


ButtonToNavigate.propTypes = {
  history: React.PropTypes.shape({
    push: React.PropTypes.func.isRequired,
  }),
};

export default withRouter(ButtonToNavigate);

3.- Używanie Redirectkomponentu

Renderowanie a <Redirect>spowoduje przejście do nowej lokalizacji. Należy jednak pamiętać, że domyślnie bieżąca lokalizacja jest zastępowana nową, jak przekierowania po stronie serwera (HTTP 3xx). Nowa lokalizacja jest zapewniona przez toprop, który może być ciągiem (URL do przekierowania) lub locationobiektem. Jeśli zamiast tego chcesz wprowadzić nowy wpis do historii , pushpodaj również rekwizyt i ustaw go natrue

<Redirect to="/your-new-location" push />

4.- Dostęp router ręczny przez kontekst

Nieco zniechęcony, ponieważ kontekst jest wciąż eksperymentalnym interfejsem API i może ulec zmianie / zmianie w przyszłych wydaniach React

const ButtonToNavigate = (props, context) => (
  <button
    type="button"
    onClick={() => context.router.history.push('/my-new-location')}
  >
    Navigate to a new location
  </button>
);

ButtonToNavigate.contextTypes = {
  router: React.PropTypes.shape({
    history: React.PropTypes.object.isRequired,
  }),
};

Nie trzeba dodawać, że istnieją również inne komponenty routera przeznaczone dla ekosystemów nieobsługujących przeglądarki, takie jak <NativeRouter>replikacja stosu nawigacji w pamięci i docelowa platforma React Native, dostępna za pośrednictwem react-router-nativepakietu.

W celu uzyskania dalszych informacji, nie wahaj się rzucić okiem na oficjalne dokumenty . Istnieje również wideo wykonane przez jednego ze współautorów biblioteki, które zapewnia całkiem fajne wprowadzenie do routera reagującego v4, podkreślając niektóre z głównych zmian.


2
Używam V4 i powyższe działa dobrze. Sporo czasu spędziłem na zabawie z routerem V4, ponieważ wydaje się, że istnieją dziwne wybory, ale powyższe zdecydowanie działa. Zakładam, że importujesz withRouterzreact-router-dom
Sam Parmenter

3
Importuję withRouterz react-router-dom. History.push zmienia adres URL, ale wydaje się, że nie ładuje, <Route>dopóki nie
wymuszę

1
@ hydrauliyohmc Myliłem się co do tego. Problem polega na tym, że mam <Router> wewnątrz dekorowanego komponentu React @observer, co powoduje ten problem . Around praca ma mieć @withRouterna każdy taki React komponent.
BreakDS

3
Dla tych, którzy natkną się na tę świetną odpowiedź, withRouterjest po prostu HOC, który używa Routepod maską. Co oznacza, że ​​używa tylko 3 rekwizytów, historii, dopasowania i lokalizacji . W powyższym przykładzie wydaje się, że pushjest to rekwizyt, withRouterktóry dodałby ButtonToNavigate, ale tak nie jest. props.history.pushmusiałby zostać użyty zamiast tego. Mam nadzieję, że to pomaga innym, którzy byli nieco zdezorientowani.
vinnymac

39
Łał. browserHistory.push('/path/some/where')po prostu wydaje się o wiele prostsze. Autorzy starają się zniechęcić do programowania imperatywnego, ale czasem działa to po prostu lepiej!
lux

149

Najłatwiejszym sposobem, aby to zrobić:

this.props.history.push("/new/url")

Uwaga:

  • Możesz przekazać element history propnadrzędny do elementu, który chcesz wywołać, jeśli nie jest dostępny.

10
Używam routera 4.0, ale na rekwizytach nie ma klucza historii. Jak mogę to naprawić?
Nicolas S.Xu,

41
Jeśli nie masz go this.props.historyw swoim komponencie, możesz, import {withRouter} from 'react-router-dom'a następnie export default withRouter(MyComponent)(lub const MyComponent = withRouter(...)), a on wstawi historyelement do rekwizytów twojego komponentu.
Malvineous

@Malvineous to ciekawe, nie wiedziałem o tym! Spróbuję!
Jikku Jose

2
Muszę przeoczyć coś fundamentalnego, ponieważ działa to dla mnie po prostu świetnie, więc nie mam pojęcia, dlaczego wszystkie odpowiedzi wymagają tak długich wyjaśnień.
Joshua Pinter

jak zapobiec ponownemu podłączeniu komponentu history.pushi po prostu uruchomić aktualizację, tak jak po kliknięciu<Link>
Rahul Yadav

55

Miałem podobny problem podczas migracji do React-Router v4, więc postaram się wyjaśnić moje rozwiązanie poniżej.

Proszę nie uważać tej odpowiedzi za właściwy sposób rozwiązania problemu, wyobrażam sobie, że istnieje spora szansa, że ​​pojawi się coś lepszego, gdy React Router v4 stanie się bardziej dojrzały i pozostawi wersję beta (może nawet już istnieć, a ja po prostu jej nie odkryłem) .

Dla kontekstu miałem ten problem, ponieważ czasami używam Redux-Saga do programowej zmiany obiektu historii (powiedzmy, kiedy użytkownik pomyślnie się uwierzytelni).

W dokumentach React Router spójrz na <Router> komponent, a zobaczysz, że masz możliwość przekazania własnego obiektu historii przez rekwizyt. To jest istota rozwiązania - możemy dostarczyć przedmiot Historia się React-Routerz punktu A globalny modułu.

Kroki:

  1. Zainstaluj moduł historii npm - yarn add history lub npm install history --save
  2. utwórz plik o nazwie history.jsw App.jsfolderze poziomu (taka była moja preferencja)

    // src/history.js
    
    import createHistory from 'history/createBrowserHistory';
    export default createHistory();`
  3. Dodaj ten obiekt historii do komponentu routera w ten sposób

    // src/App.js
    
    import history from '../your/path/to/history.js;'
    <Router history={history}>
    // Route tags here
    </Router>
  4. Dostosuj URL podobnie jak przed importując swoją globalną historię obiektu:

    import history from '../your/path/to/history.js;'
    history.push('new/path/here/');

Wszystko powinno być teraz zsynchronizowane, a ty masz również dostęp do sposobu ustawiania obiektu historii programowo, a nie poprzez komponent / kontener.


5
Ta zmiana działała dla mnie, ale tylko dlatego, że nawiguję poza komponentem. Gdybym nawigował wewnątrz komponentu takiego jak OP, użyłbym podejścia sugerowanego przez @rauliyohmc, używając rekwizytów przekazywanych przez Routekomponent.
Dan Ellis,

2
jest to zalecane podejście z dnia 17.08
Spets

2
@Spets W moim przypadku, jeśli użyję tego rodzaju podejścia, link zostanie zaktualizowany poprawnie po wypchnięciu, ale składniki nie zostaną poprawnie renderowane (np. Po zaktualizowaniu łącza składnik nie zostanie zaktualizowany, chyba że wymusisz odświeżenie strony). Gdzie znalazłeś, że jest to zalecane podejście? Jakieś linki / źródła?
fajne

2
@ScottCoates Uporządkowałem korzystając z powyższego przykładu, podając historię jako parametr, ale po tym, jak sam debugowałem moduły węzła. W sieci często występuje błąd polegający na imporcie „BrowserHistory as Router”, gdy zamiast tego istnieje inny obiekt o nazwie Router w najnowszej wersji domagania-routera. Używanie tego w połączeniu z historią utworzoną w powyższym przykładzie działa dobrze.
fajne

2
adres URL jest aktualizowany, ale strona nie jest renderowana na podstawie nowego katalogu głównego. Jakieś rozwiązanie? Dlaczego wyzwalanie trasy jest tak trudne? Ludzie, którzy reagują na projekty, nie mają rozumu?
Nicolas S.Xu,

43

TL; DR:

if (navigate) {
  return <Redirect to="/" push={true} />
}

Prosta i deklaratywna odpowiedź jest taka, że ​​musisz jej używać <Redirect to={URL} push={boolean} />w połączeniu zsetState()

push: boolean - gdy jest to prawda, przekierowanie spowoduje wypchnięcie nowego wpisu do historii zamiast zastępowania bieżącego.


import { Redirect } from 'react-router'

class FooBar extends React.Component {
  state = {
    navigate: false
  }

  render() {
    const { navigate } = this.state

    // here is the important part
    if (navigate) {
      return <Redirect to="/" push={true} />
    }
   // ^^^^^^^^^^^^^^^^^^^^^^^

    return (
      <div>
        <button onClick={() => this.setState({ navigate: true })}>
          Home
        </button>
      </div>
    )
  }
}

Pełny przykład tutaj . Przeczytaj więcej tutaj .

PS. W przykładzie użyto inicjalizatorów właściwości ES7 + do inicjalizacji stanu. Zajrzyj tutaj , jeśli jesteś zainteresowany.


5
Należy zaakceptować odpowiedź. Najprostsze eleganckie rozwiązanie! +1 dla @lustoykov
Ali Abbas Jaffri

1
W komponencie componentDidUpdate ustawiłem także opcję nawigacji z powrotem na wartość false, ponieważ mój przycisk znajduje się w nagłówku, w przeciwnym razie nawigowałbym tylko raz.
peterorum

Działa to tylko wtedy, gdy wiesz o przekierowaniu podczas ładowania strony. Jeśli czekasz na powrót asynchronicznego wywołania (tj. Uwierzytelnienia za pomocą Google lub czegoś takiego), musisz użyć jednej z history.push()metod.
brittohalloran

Nie bardzo, nadal możesz wykorzystać deklaratywną naturę reagowania w połączeniu ze składnikiem <Przekierowanie />. Jeśli strona się nie ładuje, możesz wrócić do innego <Przekierowanie />
Lyubomir

@brittohalloran ideą tej metody przy użyciu odpowiedniego routera reagującego jest upewnienie się, że używasz setState do wymuszenia ponownego renderowania.
Someone Special

16

Użyj useHistoryhaka, jeśli używasz składników funkcji

Możesz użyć useHistory hook, aby uzyskać historyinstancję.

import { useHistory } from "react-router-dom";

const MyComponent = () => {
  var history = useHistory();

  return (
    <button onClick={() => history.push("/about")}>
      Click me
    </button>
  );
}

useHistoryHak daje dostęp do instancji historii, które można wykorzystać do nawigacji.

Użyj historywłaściwości w składnikach strony

React Router wstrzykuje niektóre właściwości, w tym history składniki strony.

class HomePage extends React.Component {
  render() {
    const { history } = this.props;

    return (
      <div>
        <button onClick={() => history.push("/projects")}>
          Projects
        </button>
      </div>
    );
  }
}

Zawiń elementy potomne withRouter aby wprowadzić właściwości routera

withRouterotoki wstrzykuje właściwości routera do komponentów. Na przykład możesz użyć tego opakowania, aby wstrzyknąć router do wylogowania komponentu przycisku umieszczonego w menu użytkownika.

import { withRouter } from "react-router";

const LogoutButton = withRouter(({ history }) => {
  return (
    <button onClick={() => history.push("/login")}>
      Logout
    </button>
  );
});

export default LogoutButton;

11

Możesz także po prostu użyć rekwizytów, aby uzyskać dostęp do obiektu historii: this.props.history.push('new_url')


5
Przydatne tylko w komponencie bezpośrednio pochodzącym od routera. Aby nie przekazać propozycji historii każdemu elementowi, w którym potrzebujesz tej funkcji.
mwieczorek

3
Jeśli nie masz go this.props.historyw swoim komponencie, możesz, import {withRouter} from 'react-router-dom'a następnie export default withRouter(MyComponent)(lub const MyComponent = withRouter(...)), a on wstawi historyelement do rekwizytów twojego komponentu.
Malvineous

9

Krok 1: na wierzch można zaimportować tylko jedną rzecz:

import {Route} from 'react-router-dom';

Krok 2: Przełóż historię na swojej trasie:

<Route
  exact
  path='/posts/add'
  render={({history}) => (
    <PostAdd history={history} />
  )}
/>

Krok 3: Historia zostanie zaakceptowana jako część rekwizytów w następnym Komponencie, więc możesz po prostu:

this.props.history.push('/');

To było łatwe i naprawdę potężne.


7

To działa:

import { withRouter } from 'react-router-dom';

const SomeComponent = withRouter(({ history }) => (
    <div onClick={() => history.push('/path/some/where')}>
        some clickable element
    </div>); 
);

export default SomeComponent;

5

Moja odpowiedź jest podobna do Alexa . Nie jestem pewien, dlaczego React-Router uczynił to tak niepotrzebnie skomplikowanym. Dlaczego powinienem owijać mój komponent HoC, aby uzyskać dostęp do tego, co zasadniczo jest globalne?

W każdym razie, jeśli spojrzysz na ich implementację <BrowserRouter>, to tylko małe opakowanie historii .

Możemy wyciągnąć nieco tę historię, abyśmy mogli ją zaimportować z dowolnego miejsca. Jednak sztuczka polega na tym, że jeśli renderujesz po stronie serwera i próbujesz przejść importdo modułu historii, nie zadziała, ponieważ używa interfejsów API tylko przeglądarki. Ale to w porządku, ponieważ zwykle przekierowujemy tylko w odpowiedzi na kliknięcie lub inne zdarzenie po stronie klienta. Dlatego prawdopodobnie jest to poprawne:

// history.js
if(__SERVER__) {
    module.exports = {};
} else {
    module.exports = require('history').createBrowserHistory();
}

Za pomocą pakietu internetowego możemy zdefiniować niektóre zmienne, abyśmy wiedzieli, w jakim środowisku się znajdujemy:

plugins: [
    new DefinePlugin({
        '__SERVER__': 'false',
        '__BROWSER__': 'true', // you really only need one of these, but I like to have both
    }),

A teraz możesz

import history from './history';

Skądkolwiek. Zwróci tylko pusty moduł na serwerze.

Jeśli nie chcesz używać tych magicznych zmiennych, musisz po prostu znaleźć się requirew globalnym obiekcie tam, gdzie jest to potrzebne (wewnątrz modułu obsługi zdarzeń). importnie będzie działać, ponieważ działa tylko na najwyższym poziomie.


6
cholera, zrobili to tak skomplikowanym.
Abhishek

4
Całkowicie się z tobą zgodziłem. jest to tak skomplikowane jak sama nawigacja
Thai Tran

5

Myślę, że @rgommezz obejmuje większość przypadków minus jeden, który moim zdaniem jest dość ważny.

// history is already a dependency or React Router, but if don't have it then try npm install save-dev history

import createHistory from "history/createBrowserHistory"

// in your function then call add the below 
const history = createHistory();
// Use push, replace, and go to navigate around.
history.push("/home");

To pozwala mi napisać prostą usługę z działaniami / wywołaniami, które mogę wywołać, aby wykonać nawigację z dowolnego komponentu, który chcę, bez robienia HoC na moich komponentach ...

Nie jest jasne, dlaczego nikt wcześniej nie dostarczył tego rozwiązania. Mam nadzieję, że to pomoże, a jeśli zauważysz jakiś problem, daj mi znać.


4

Testuję v4 od kilku dni i .. Jak dotąd kocham to! Po chwili ma to sens.

Miałem również to samo pytanie i uznałem, że radzenie sobie z nim tak, jak poniżej, działa najlepiej (a może nawet tak, jak jest zamierzone). Wykorzystuje stan, operator trójskładnikowy i <Redirect>.

W konstruktorze ()

this.state = {
    redirectTo: null
} 
this.clickhandler = this.clickhandler.bind(this);

W render ()

render(){
    return (
        <div>
        { this.state.redirectTo ?
            <Redirect to={{ pathname: this.state.redirectTo }} /> : 
            (
             <div>
               ..
             <button onClick={ this.clickhandler } />
              ..
             </div>
             )
         }

W module obsługi kliknięć ()

 this.setState({ redirectTo: '/path/some/where' });

Mam nadzieję, że to pomoże. Daj mi znać.


Czy przy tej metodzie są jakieś pułapki? W moim projekcie działa tylko wtedy, gdy ustawię stan w konstruktorze, stamtąd mogę przekierować na dowolną stronę, którą chcę. Ale kiedy ustawiam stan na zdarzenie (rekwizyty się zmieniły, na przykład) widzę metodę renderowania wywoływaną z nowym stanem, ale przekierowanie się nie zdarza. Widzę tę samą stronę
Dmitry Malugin

Pułapka polega na tym, że zastąpi historię, więc nie będziesz w stanie odeprzeć - tak właściwie to nie jest dobre rozwiązanie.
dannytenaglias

4

Zmagałem się z tym przez jakiś czas - coś tak prostego, ale tak skomplikowanego, ponieważ ReactJS to po prostu zupełnie inny sposób pisania aplikacji internetowych, jest bardzo obcy dla starszych ludzi!

Stworzyłem osobny komponent, aby odciąć bałagan:

// LinkButton.js

import React from "react";
import PropTypes from "prop-types";
import {Route} from 'react-router-dom';

export default class LinkButton extends React.Component {

    render() {
        return (
            <Route render={({history}) => (
                <button {...this.props}
                       onClick={() => {
                           history.push(this.props.to)
                       }}>
                    {this.props.children}
                </button>
            )}/>
        );
    }
}

LinkButton.propTypes = {
    to: PropTypes.string.isRequired
};

Następnie dodaj go do swojej render()metody:

<LinkButton className="btn btn-primary" to="/location">
    Button Text
</LinkButton>

Uważam to rozwiązanie za bardzo przydatne. Kopiuję kod. Daj mi znać, że umieściłeś go na githubie - bezpośrednio ci go przypisuję.
Abhinav Manchanda

3

Ponieważ nie ma innego sposobu radzenia sobie z tym okropnym projektem, napisałem ogólny komponent, który wykorzystuje podejście withRouter HOC . W poniższym przykładzie jest zawijanie buttonelementu, ale możesz zmienić dowolny potrzebny element, który można kliknąć:

import React from 'react';
import PropTypes from 'prop-types';
import { withRouter } from 'react-router-dom';

const NavButton = (props) => (
  <Button onClick={() => props.history.push(props.to)}>
    {props.children}
  </Button>
);

NavButton.propTypes = {
  history: PropTypes.shape({
    push: PropTypes.func.isRequired
  }),
  to: PropTypes.string.isRequired
};

export default withRouter(NavButton);

Stosowanie:

<NavButton to="/somewhere">Click me</NavButton>

3
this.props.history.push("/url")

Jeśli nie znalazłeś pliku this.props.history w swoim komponencie, spróbuj tego

import {withRouter} from 'react-router-dom'
export default withRouter(MyComponent)  

Dzięki wielkie!
QauseenMZ

1

Ponieważ czasami wolę przełączać trasy według aplikacji niż przycisków, jest to minimalny działający przykład, który działa dla mnie:

import { Component } from 'react'
import { BrowserRouter as Router, Link } from 'react-router-dom'

class App extends Component {
  constructor(props) {
    super(props)

    /** @type BrowserRouter */
    this.router = undefined
  }

  async handleSignFormSubmit() {
    await magic()
    this.router.history.push('/')
  }

  render() {
    return (
      <Router ref={ el => this.router = el }>
        <Link to="/signin">Sign in</Link>
        <Route path="/signin" exact={true} render={() => (
          <SignPage onFormSubmit={ this.handleSignFormSubmit } />
        )} />
      </Router>
    )
  }
}

0

Dla tych z Was, którzy wymagają przekierowania przed pełnym zainicjowaniem routera za pomocą React Routerlub React Router DomMożesz zapewnić przekierowanie, po prostu uzyskując dostęp do obiektu historii i wpychając na niego nowy stan w swojej konstrukcji app.js. Rozważ następujące:

function getSubdomain(hostname) {
    let regexParse = new RegExp('[a-z\-0-9]{2,63}\.[a-z\.]{2,5}$');
    let urlParts = regexParse.exec(hostname);
    return hostname.replace(urlParts[0], '').slice(0, -1);
}

class App extends Component {

    constructor(props) {
        super(props);


        this.state = {
            hostState: true
        };

        if (getSubdomain(window.location.hostname).length > 0) {
            this.state.hostState = false;
            window.history.pushState('', '', './login');
        } else {
            console.log(getSubdomain(window.location.hostname));
        }

    }


    render() {
        return (

            <BrowserRouter>
                {this.state.hostState ? (
                    <div>
                        <Route path="/login" component={LoginContainer}/>
                        <Route path="/" component={PublicContainer}/>
                    </div>
                ) : (
                    <div>
                        <Route path="/login" component={LoginContainer}/>
                    </div>
                )

                }
            </BrowserRouter>)
    }


}

W tym miejscu chcemy zmienić trasy wyjściowe zależne od poddomeny, wchodząc w interakcję z obiektem historii przed renderowaniem komponentu, możemy skutecznie przekierować, pozostawiając nasze trasy taktowne.

window.history.pushState('', '', './login');
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.