493 votes

Comment pousser à l'historique dans React Router v4?

Dans la version actuelle de Réagir Routeur (v3), je peux accepter une réponse du serveur et de l'utiliser browserHistory.push aller à la réponse appropriée de la page. Cependant, ce n'est pas disponible dans la version 4, et je ne suis pas sûr de la façon de gérer cela est.

Dans cet exemple, à l'aide de Redux, components/app-product-form.js appels this.props.addProduct(props) lorsqu'un utilisateur soumet le formulaire. Lorsque le serveur renvoie un succès, l'utilisateur est pris à la page du Panier.

// actions/index.js
export function addProduct(props) {
  return dispatch =>
    axios.post(`${ROOT_URL}/cart`, props, config)
      .then(response => {
        dispatch({ type: types.AUTH_USER });
        localStorage.setItem('token', response.data.token);
        browserHistory.push('/cart'); // no longer in React Router V4
      });
}

Comment puis-je faire une redirection vers la page du Panier à partir de la fonction pour Réagir Routeur v4?

405voto

Oleg Belostotsky Points 2582

Vous pouvez utiliser l' history méthodes en dehors de vos composants. Essayez de la façon suivante.

Tout d'abord, créez un history objet utilisé l'histoire de package:

// src/history.js

import { createBrowserHistory } from 'history';

export default createBrowserHistory();

Puis enveloppez - <Router> (veuillez noter, vous devez utiliser import { Router } au lieu de import { BrowserRouter as Router }):

// src/index.jsx

// ...
import { Router, Route, Link } from 'react-router-dom';
import history from './history';

ReactDOM.render(
  <Provider store={store}>
    <Router history={history}>
      <div>
        <ul>
          <li><Link to="/">Home</Link></li>
          <li><Link to="/login">Login</Link></li>
        </ul>
        <Route exact path="/" component={HomePage} />
        <Route path="/login" component={LoginPage} />
      </div>
    </Router>
  </Provider>,
  document.getElementById('root'),
);

Changer votre emplacement actuel à partir d'un lieu, par exemple:

// src/actions/userActionCreators.js

// ...
import history from '../history';

export function login(credentials) {
  return function (dispatch) {
    return loginRemotely(credentials)
      .then((response) => {
        // ...
        history.push('/');
      });
  };
}

UPD: Vous pouvez également voir un exemple légèrement différent de Réagir Routeur FAQ.

390voto

Chris Points 3970

Réagir Routeur v4 est fondamentalement différente de la v3 (et plus tôt) et vous ne pouvez pas faire browserHistory.push() comme vous avez utilisé pour.

Cette discussion semble liée, si vous voulez plus d'info:

  • La création d'un nouveau browserHistory ne fonctionnera pas parce que <BrowserRouter> crée sa propre histoire instance, et à l'écoute pour des changements. Afin qu'une autre instance de changer l'url, mais pas de mise à jour de l' <BrowserRouter>.
  • browserHistory n'est pas exposée par réagissent-routeur dans la v4, seulement dans la v2.

Au lieu de cela, vous avez quelques options pour ce faire:

  • Utiliser l' withRouter haute-composante de l'ordre

    Au lieu de cela, vous devez utiliser l' withRouter haute composante de l'ordre, et étirable à l'élément qui va pousser à l'histoire. Par exemple:

    import React from "react";
    import { withRouter } from "react-router-dom";
    
    class MyComponent extends React.Component {
      ...
      myFunction() {
        this.props.history.push("/some/Path");
      }
      ...
    }
    export default withRouter(MyComponent);
    

    Consultez la documentation officielle pour plus d'info:

    Vous pouvez obtenir l'accès à l' history propriétés de l'objet le plus proche <Route>s' match via le withRouter d'ordre supérieur composant. withRouter ré-rendu de son composant à chaque fois les changements de route avec les mêmes accessoires que <Route> le rendu des accessoires: { match, location, history }.


  • Utiliser l' context API

    À l'aide du contexte peut être une des solutions les plus simples, mais étant expérimentale de l'API, elle est instable et non pris en charge. Utiliser seulement quand tout le reste échoue. Voici un exemple:

    import React from "react";
    import PropTypes from "prop-types";
    
    class MyComponent extends React.Component {
      static contextTypes = {
        router: PropTypes.object
      }
      constructor(props, context) {
         super(props, context);
      }
      ...
      myFunction() {
        this.context.router.history.push("/some/Path");
      }
      ...
    }
    

    Jetez un oeil à la documentation officielle sur le contexte:

    Si vous souhaitez que votre application soit stable, ne pas utiliser le contexte. C'est un dispositif expérimental de l'API et il est susceptible de se rompre dans les futures versions de Réagir.

    Si vous insistez sur l'utilisation d'un contexte en dépit de ces avertissements, essayez d'isoler votre utilisation du contexte pour une petite surface et d'éviter d'utiliser le contexte de l'API directement lorsque possible, de sorte qu'il est plus facile de mettre à niveau lorsque les changements de l'API.

27voto

Michael Horojanski Points 1567

Voici comment je l'ai fait:

 import React, {Component} from 'react';

export default class Link extends Component {
    constructor(props) {
        super(props);
        this.onLogout = this.onLogout.bind(this);
    }
    onLogout() {
        this.props.history.push('/');
    }
    render() {
        return (
            <div>
                <h1>Your Links</h1>
                <button onClick={this.onLogout}>Logout</button>
            </div>
        );
    }
}
 

Utilisez this.props.history.push('/cart'); pour rediriger vers la page du panier. Elle sera enregistrée dans un objet historique.

Profitez, Michael.

23voto

alainbex Points 329

Selon Réagir Routeur v4 documentation - Redux l'Intégration en Profondeur de la session

L'intégration en profondeur est nécessaire pour:

"être capable de naviguer par l'envoi d'actions"

Toutefois, ils recommandent cette approche comme une alternative à la "intégration profonde":

"Plutôt que de dispatching des actions pour naviguer, vous pouvez passer à l'histoire de l'objet fourni pour acheminer les composants de vos actions et de naviguer avec elle."

De sorte que vous pouvez envelopper votre composant avec le withRouter forte composante de l'ordre:

export default withRouter(connect(null, { actionCreatorName })(ReactComponent));

qui va passer à l'histoire de l'API pour les accessoires. Vous pouvez donc appeler l'action créateur de passage de l'histoire en tant que param. Par exemple, à l'intérieur de votre ReactComponent:

onClick={() => {
  this.props.actionCreatorName(
    this.props.history,
    otherParams
  );
}}

Puis, à l'intérieur de votre actions/index.js:

export function actionCreatorName(history, param) {
  return dispatch => {
    dispatch({
      type: SOME_ACTION,
      payload: param.data
    });
    history.push("/path");
  };
}

19voto

Khrystyna Skvarok Points 608

Mauvaise question, ça m'a pris pas mal de temps, mais finalement, je l'ai résolue de cette façon:

Enveloppez votre conteneur avec withRouter et passez l’historique de votre action dans la fonction mapDispatchToProps . En action, utilisez history.push ('/ url') pour naviguer.

Action:

 export function saveData(history, data) {
  fetch.post('/save', data)
     .then((response) => {
       ...
       history.push('/url');
     })
};
 

Récipient:

 import { withRouter } from 'react-router-dom';
...
const mapDispatchToProps = (dispatch, ownProps) => {
  return {
    save: (data) => dispatch(saveData(ownProps.history, data))}
};
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Container));
 

Ceci est valable pour React Router v4.x.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X