Naviguer par programme en utilisant Reactor V4

336

Je viens de remplacer la react-routerv3 en v4.
Mais je ne sais pas comment naviguer par programmation dans la fonction membre de a Component. c'est-à-dire dans la handleClick()fonction que je veux naviguer après /path/some/whereavoir traité certaines données. Je le faisais par:

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

Mais je ne trouve pas de telles interfaces dans la v4.
Comment naviguer avec v4?

Colin Witkamp
la source
3
Vous pouvez accéder à l'objet historique dans v4 via des accessoires: this.props.history.push ('/')
colemerrick
6
Et si vous voulez y accéder à partir d'un endroit différent d'un Component? Par exemple, à l'intérieur des actions redux.
Maximus S
73
parfois je me demande pourquoi il est si compliqué de simplement passer d'un lien à l'autre =))
Thai Tran
12
On pourrait penser qu'à cette époque, la redirection ne serait pas si compliquée.
JohnAllen
J'ai trouvé cet article utile: medium.com/@anneeb/redirecting-in-react-4de5e517354a
BioData41

Réponses:

414

Si vous ciblez des environnements de navigateur, vous devez utiliser le react-router-dompackage au lieu de react-router. Ils suivent la même approche que React, afin de séparer le noyau, ( react) et le code spécifique à la plate-forme, ( react-dom, react-native) avec la différence subtile que vous n'avez pas besoin d'installer deux packages distincts, de sorte que les packages d'environnement contiennent tout vous avez besoin. Vous pouvez l'ajouter à votre projet comme:

yarn add react-router-dom

ou

npm i react-router-dom

La première chose que vous devez faire est de fournir un <BrowserRouter>composant le plus parent dans votre application. <BrowserRouter>utilise l' historyAPI HTML5 et le gère pour vous, vous n'avez donc pas à vous soucier de l'instancier vous-même et de le transmettre au <BrowserRouter>composant comme accessoire (comme vous le deviez dans les versions précédentes).

Dans la V4, pour naviguer par programmation, vous devez accéder à l' historyobjet, qui est disponible via React context, tant que vous avez un composant <BrowserRouter> fournisseur en tant que parent le plus parent de votre application. La bibliothèque expose à travers le contexte l' routerobjet, qui lui-même contient historycomme propriété. L' historyinterface propose plusieurs méthodes de navigation, telles que push, replaceet goBack, entre autres. Vous pouvez consulter la liste complète des propriétés et méthodes ici .

Remarque importante pour les utilisateurs de Redux / Mobx

Si vous utilisez redux ou mobx comme bibliothèque de gestion d'état dans votre application, vous pouvez avoir rencontré des problèmes avec des composants qui devraient être sensibles à l'emplacement mais qui ne sont pas restitués après le déclenchement d'une mise à jour d'URL

Cela se produit car react-routerpasse locationaux composants à l'aide du modèle de contexte.

La connexion et l'observateur créent des composants dont les méthodes shouldComponentUpdate font une comparaison superficielle de leurs accessoires actuels et de leurs prochains accessoires. Ces composants ne seront restitués que lorsqu'au moins un accessoire a changé. Cela signifie que pour garantir leur mise à jour lorsque l'emplacement change, ils devront recevoir un accessoire qui change lorsque l'emplacement change.

Les 2 approches pour résoudre ce problème sont:

  • Enveloppez votre composant connecté dans un chemin sans chemin <Route />. L' locationobjet actuel est l'un des accessoires qu'un <Route>passe au composant qu'il rend
  • Enveloppez votre composant connecté avec le withRoutercomposant d'ordre supérieur, qui a en fait le même effet et injecte locationqu'un accessoire

En mettant cela de côté, il existe quatre façons de naviguer par programme, ordonnées par recommandation:

1.- Utilisation d'un <Route>composant

Il promeut un style déclaratif. Avant la v4, les <Route />composants étaient placés en haut de votre hiérarchie de composants, en pensant au préalable à la structure de vos itinéraires. Cependant, vous pouvez maintenant avoir des <Route>composants n'importe où dans votre arborescence, ce qui vous permet d'avoir un contrôle plus fin pour le rendu conditionnel en fonction de l'URL. Routeinjecte match, locationet historycomme accessoires dans votre composant. Les méthodes de navigation ( par exemple push, replace, goBack...) sont disponibles en tant que propriétés de l' historyobjet.

Il y a 3 façons de rendre quelque chose avec un Route, en utilisant soit component, rendersoit des childrenaccessoires, mais n'en utilisez pas plus d'un en même temps Route. Le choix dépend du cas d'utilisation, mais fondamentalement, les deux premières options ne rendront votre composant que s'il pathcorrespond à l'emplacement de l'URL, tandis qu'avec childrenle composant sera rendu si le chemin correspond à l'emplacement ou non (utile pour ajuster l'interface utilisateur en fonction de l'URL correspondant à).

Si vous souhaitez personnaliser votre composant de rendu de sortie , vous devez envelopper votre composant dans une fonction et utilisez l' renderoption pour passer à votre composant les autres accessoires que vous désirez, à part match, locationet history. Un exemple pour illustrer:

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.- Utiliser withRouterHoC

Ce composant d'ordre supérieur injectera les mêmes accessoires que Route. Cependant, il comporte la limitation selon laquelle vous ne pouvez avoir qu'une seule HoC par fichier.

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.- Utiliser un Redirectcomposant

Le rendu a <Redirect>permet d'accéder à un nouvel emplacement. Mais gardez à l'esprit que, par défaut , l'emplacement actuel est remplacé par le nouveau, comme les redirections côté serveur (HTTP 3xx). Le nouvel emplacement est fourni par toprop, qui peut être une chaîne (URL vers laquelle rediriger) ou un locationobjet. Si vous souhaitez plutôt insérer une nouvelle entrée dans l'historique , passez également un pushaccessoire et définissez-le surtrue

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

4.- Accès routermanuel via le contexte

Un peu découragé car le contexte est toujours une API expérimentale et il est susceptible de se casser / changer dans les futures versions de 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,
  }),
};

Inutile de dire qu'il existe également d'autres composants de routeur destinés à des écosystèmes autres que des navigateurs, tels que ceux <NativeRouter>qui reproduisent une pile de navigation en mémoire et ciblent la plate-forme React Native, disponibles via le react-router-nativepackage.

Pour toute référence supplémentaire, n'hésitez pas à consulter les documents officiels . Il y a aussi une vidéo réalisée par l'un des co-auteurs de la bibliothèque qui fournit une introduction assez cool à react-router v4, mettant en évidence certains des changements majeurs.

rgommezz
la source
2
J'utilise V4 et ce qui précède fonctionne très bien. J'ai passé pas mal de temps à fouiner avec le routeur V4 car il semble que certains choix soient étranges, mais ce qui précède fonctionne certainement. Je suppose que vous importez withRouterdereact-router-dom
Sam Parmenter
3
J'importe withRouterde react-router-dom. Le history.push change l'url, mais il ne semble pas le charger <Route>jusqu'à ce que je force à rafraîchir la page ...
BreakDS
1
@rauliyohmc J'avais tort à ce sujet. Le problème est que j'ai à l' <Router> intérieur un composant React qui est décoré @observer, ce qui déclenche ce problème . Le travail consiste à disposer @withRouterde chacun de ces composants React.
BreakDS
3
Pour ceux qui rencontrent cette excellente réponse, withRouterc'est tout simplement un HOC qui utilise un Routesous le capot. Ce qui signifie qu'il n'utilise que 3 accessoires, historique, correspondance et emplacement . Dans l'exemple ci-dessus, il semble que ce pushsoit un accessoire qui withRouterviendrait s'ajouter ButtonToNavigate, mais ce n'est pas le cas. props.history.pushdevrait être utilisé à la place. J'espère que cela aide ceux qui étaient un peu confus.
vinnymac
39
Sensationnel. browserHistory.push('/path/some/where')semble juste beaucoup plus simple. Les auteurs tentent de décourager la programmation impérative, mais parfois cela fonctionne mieux!
lux
149

La façon la plus simple de le faire:

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

Remarque:

  • Vous souhaiterez peut-être transmettre le history propcomposant parent parent au composant auquel vous souhaitez appeler l'action s'il n'est pas disponible.
Jikku Jose
la source
10
J'utilise un routeur 4.0, mais il n'y a pas de clé d'historique sur les accessoires. Comment puis-je le réparer?
Nicolas S.Xu
41
Si vous n'en avez pas this.props.historydans votre composant, vous pouvez import {withRouter} from 'react-router-dom'et puis export default withRouter(MyComponent)(ou const MyComponent = withRouter(...)) et il insérera l' historyélément dans les accessoires de votre composant.
Malvineous
@Malvine c'est intéressant, je n'en savais rien! Je vais l'essayer!
Jikku Jose
2
Je dois manquer quelque chose de fondamental, car cela fonctionne très bien pour moi, donc je n'ai aucune idée pourquoi toutes les réponses nécessitent des explications aussi longues.
Joshua Pinter
comment empêcher le remontage des composants history.pushet simplement déclencher la mise à jour comme lorsque nous cliquons sur<Link>
Rahul Yadav
55

J'ai eu un problème similaire lors de la migration vers React-Router v4, je vais donc essayer d'expliquer ma solution ci-dessous.

Veuillez ne pas considérer cette réponse comme la bonne façon de résoudre le problème, j'imagine qu'il y a de bonnes chances que quelque chose de mieux se produise lorsque React Router v4 devient plus mature et quitte la version bêta (il peut même déjà exister et je ne l'ai tout simplement pas découvert) .

Pour le contexte, j'ai eu ce problème parce que j'utilise occasionnellement Redux-Sagapour modifier par programme l'objet historique (par exemple, lorsqu'un utilisateur réussit à s'authentifier).

Dans les documents React Router, jetez un œil au <Router> composant et vous pouvez voir que vous avez la possibilité de passer votre propre objet historique via un accessoire. C'est l'essence de la solution - nous fournissons l'objet historique àReact-Router partir d'un module global .

Pas:

  1. Installer le module d'historique npm - yarn add history ou npm install history --save
  2. créer un fichier appelé history.jsdans votre App.jsdossier level (c'était ma préférence)

    // src/history.js
    
    import createHistory from 'history/createBrowserHistory';
    export default createHistory();`
  3. Ajoutez cet objet d'historique à votre composant de routeur comme ceci

    // src/App.js
    
    import history from '../your/path/to/history.js;'
    <Router history={history}>
    // Route tags here
    </Router>
  4. Ajustez l'URL comme avant en important votre objet d'historique global:

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

Tout devrait rester synchronisé maintenant, et vous avez également accès à un moyen de définir l'objet historique par programme et non via un composant / conteneur.

Alex Mann
la source
5
Ce changement a fonctionné pour moi, mais uniquement parce que je navigue en dehors d'un composant. Si je naviguais à l'intérieur d'un composant comme l'OP, j'utiliserais l'approche suggérée par @rauliyohmc en utilisant les accessoires transmis par le Routecomposant.
Dan Ellis
2
c'est l'approche recommandée à partir du 08/17
Spets
2
@Spets Dans mon cas, si j'utilise ce type d'approche, le lien sera mis à jour correctement après le push, mais les composants ne seront pas rendus correctement (par exemple, après la mise à jour du lien, le composant n'est pas mis à jour sauf si vous forcez l'actualisation de la page). Où avez-vous constaté que cette approche est recommandée? Des liens / sources?
cool
2
@ScottCoates J'ai trié en utilisant l'exemple ci-dessus, en effet en fournissant l'historique en tant que paramètre, mais après avoir fait le débogage des modules de nœud par moi-même. Il y a une erreur courante commise sur tout le Web, en utilisant l'importation de "BrowserHistory as Router", alors qu'à la place il y a un autre objet appelé Router par lui-même dans la dernière version de react-router-dom. Utiliser cela en combinaison avec l'historique créé dans l'exemple ci-dessus fonctionne très bien.
cool
2
l'url est mise à jour, mais la page n'est pas rendue en fonction de la nouvelle racine. Toute solution? Pourquoi déclencher l'itinéraire est-il si difficile? Les gens qui conçoivent réagissent est-ce fou?
Nicolas S.Xu
43

TL; DR:

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

La réponse simple et déclarative est que vous devez utiliser <Redirect to={URL} push={boolean} />en combinaison avecsetState()

push: boolean - lorsque true, la redirection poussera une nouvelle entrée dans l'historique au lieu de remplacer l'actuelle.


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

Exemple complet ici . Lisez plus ici .

PS. L'exemple utilise ES7 + Property Initializers pour initialiser l'état. Regardez ici aussi, si vous êtes intéressé.

Lyubomir
la source
5
Cette réponse devrait être acceptée. Solution élégante la plus simple! +1 pour @lustoykov
Ali Abbas Jaffri
1
J'ai également défini la navigation sur false dans componentDidUpdate car mon bouton est dans un en-tête et ne naviguerait autrement qu'une seule fois.
peterorum
Cela ne fonctionne que si vous connaissez la redirection lorsque la page se charge. Si vous attendez le retour d'un appel asynchrone (c'est-à-dire l'authentification avec Google ou autre), vous devrez utiliser l'une des history.push()méthodes.
brittohalloran
Pas vraiment, vous pouvez toujours tirer parti de la nature déclarative de react combiné avec le composant <Redirect />. Si la page ne se charge pas, vous pouvez revenir à une autre <Redirect />
Lyubomir
@brittohalloran l'idée de cette méthode en utilisant le routeur de réaction approprié, est de s'assurer que vous utilisez setState pour forcer un nouveau rendu.
Quelqu'un spécial
16

Utilisation useHistory crochet si vous utilisez des composants de fonction

Vous pouvez utiliser le useHistoryhook pour obtenir une historyinstance.

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

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

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

le useHistory hook vous donne accès à l'instance d'historique que vous pouvez utiliser pour naviguer.

Utilisation history propriété à l'intérieur des composants de la page

React Router injecte certaines propriétés, y compris les historycomposants de page.

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

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

Enveloppez les composants enfants withRouterpour injecter les propriétés du routeur

withRouterle wrapper injecte les propriétés du routeur aux composants. Par exemple, vous pouvez utiliser ce wrapper pour injecter un composant de bouton de déconnexion du routeur placé dans le menu utilisateur.

import { withRouter } from "react-router";

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

export default LogoutButton;
TheMisir
la source
11

Vous pouvez également simplement utiliser des accessoires pour accéder à l'objet historique: this.props.history.push('new_url')

user1445685
la source
5
Utile uniquement lorsque le composant descend directement du routeur. De peur que vous ne transmettiez l'accessoire d'historique à chaque composant dans
lequel
3
Si vous n'en avez pas this.props.historydans votre composant, vous pouvez import {withRouter} from 'react-router-dom'et puis export default withRouter(MyComponent)(ou const MyComponent = withRouter(...)) et il insérera l' historyélément dans les accessoires de votre composant.
Malvineous
9

Étape 1: Il n'y a qu'une seule chose à importer par dessus:

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

Étape 2: Dans votre itinéraire, passez l'historique:

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

Étape 3: l'historique est accepté comme partie des accessoires dans le prochain composant, vous pouvez donc simplement:

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

C'était facile et vraiment puissant.

cdi-meo
la source
7

Cela marche:

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

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

export default SomeComponent;
Kaya Toast
la source
5

Ma réponse est similaire à celle d' Alex . Je ne sais pas pourquoi React-Router a rendu cela si compliqué inutilement. Pourquoi devrais-je avoir à envelopper mon composant avec un HoC juste pour avoir accès à ce qui est essentiellement un global?

Quoi qu'il en soit, si vous regardez comment ils ont été mis en œuvre <BrowserRouter>, ce n'est qu'un petit tour d'horizon de l' histoire .

Nous pouvons extraire cet historique pour pouvoir l'importer de n'importe où. L'astuce, cependant, est que si vous effectuez un rendu côté serveur et que vous essayez importle module d'historique, cela ne fonctionnera pas car il utilise des API uniquement pour le navigateur. Mais c'est OK car nous ne redirigeons généralement qu'en réponse à un clic ou à un autre événement côté client. Il est donc probablement OK de le simuler:

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

Avec l'aide de webpack, nous pouvons définir quelques vars afin que nous sachions dans quel environnement nous sommes:

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

Et maintenant vous pouvez

import history from './history';

De partout. Cela ne fera que renvoyer un module vide sur le serveur.

Si vous ne voulez pas utiliser ces vars magiques, vous n'aurez qu'à le faire requiredans l'objet global où il est nécessaire (à l'intérieur de votre gestionnaire d'événements). importne fonctionnera pas car il ne fonctionne qu'au niveau supérieur.

mpen
la source
6
putain ils ont rendu ça si compliqué.
Abhishek
4
Je suis totalement d'accord avec toi. c'est tellement compliqué pour une simple navigation
Thai Tran
5

Je pense que @rgommezz couvre la plupart des cas moins celui que je pense que c'est assez important.

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

Cela me permet d'écrire un service simple avec des actions / appels que je peux appeler pour faire la navigation depuis n'importe quel composant que je veux sans faire beaucoup de HoC sur mes composants ...

On ne sait pas pourquoi personne n'a fourni cette solution auparavant. J'espère que cela aide, et si vous voyez un problème avec lui, faites le moi savoir.

user3053247
la source
4

Je teste la v4 depuis quelques jours maintenant et .. je l'adore jusqu'à présent! Cela prend tout son sens après un certain temps.

J'ai également eu la même question et j'ai trouvé que la gérer comme celle-ci fonctionnait le mieux (et pourrait même être la façon dont elle est prévue). Il utilise l'état, un opérateur ternaire et<Redirect> .

Dans le constructeur ()

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

Dans le rendu ()

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

Dans le gestionnaire de clics ()

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

J'espère que ça aide. Faites le moi savoir.

jar0m1r
la source
Y a-t-il des pièges avec cette méthode? Dans mon projet avec des travaux uniquement lorsque je mets l'état dans le constructeur, je peux rediriger vers n'importe quelle page que je veux. Mais quand je définis l'état sur l'événement (les accessoires ont changé, par exemple), je vois la méthode de rendu appelée avec un nouvel état, mais la redirection ne se produit pas, je vois la même page
Dmitry Malugin
Le piège est qu'il remplacera l'historique, donc vous ne pourrez pas riposter - donc, fondamentalement, ce n'est pas une bonne solution.
dannytenaglias
4

Je me suis débattu avec cela pendant un certain temps - quelque chose de si simple, mais si compliqué, parce que ReactJS est juste une façon complètement différente d'écrire des applications Web, c'est très étranger pour nous, les personnes âgées!

J'ai créé un composant séparé pour faire abstraction du gâchis:

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

Ajoutez-le ensuite à votre render()méthode:

<LinkButton className="btn btn-primary" to="/location">
    Button Text
</LinkButton>
mwieczorek
la source
Je trouve cette solution très utile. Je copie le code. Faites-moi savoir que vous l'avez mis sur github - je vous l'attribuerai directement.
Abhinav Manchanda
3

Puisqu'il n'y a pas d'autre moyen de faire face à cette conception horrible, j'ai écrit un composant générique qui utilise l' approche withRouter HOC . L'exemple ci-dessous buttonencapsule un élément, mais vous pouvez passer à n'importe quel élément cliquable dont vous avez besoin:

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

Usage:

<NavButton to="/somewhere">Click me</NavButton>
Rodrigo
la source
3
this.props.history.push("/url")

Si vous n'avez pas trouvé this.props.history disponible dans votre composant, essayez ceci

import {withRouter} from 'react-router-dom'
export default withRouter(MyComponent)  
Shashwat Gupta
la source
Merci beaucoup!
QauseenMZ
1

Comme parfois je préfère changer de route par application puis par boutons, c'est un exemple de travail minimal qui fonctionne pour moi:

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>
    )
  }
}
piotr_cz
la source
0

Pour ceux d'entre vous qui ont besoin de rediriger avant d'initialiser complètement un routeur à l'aide de React Routerou React Router DomVous pouvez fournir une redirection en accédant simplement à l'objet historique et en poussant un nouvel état dessus dans votre construction de app.js. Considérer ce qui suit:

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


}

Ici, nous voulons changer les routes de sortie dépendant d'un sous-domaine, en interagissant avec l'objet historique avant que le composant ne soit rendu, nous pouvons effectivement rediriger tout en laissant nos routes intactes.

window.history.pushState('', '', './login');
li x
la source