web-dev-qa-db-fra.com

Navigation par programme dans React-Router v4

Je ne pouvais pas attendre et j'ai sauté dans l'utilisation de la dernière version alpha de react-router v4. Le tout nouveau <BrowserRouter/> est très utile pour que votre interface utilisateur reste synchronisée avec l'historique du navigateur, mais comment l'utiliser pour naviguer par programmation?

31
spik3s

Le routeur ajoutera un objet history à votre composant dans le hash props. Donc dans votre composant, faites simplement:

this.props.history.Push('/mypath')

Voici un exemple complet:

Dans App.js:

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

import Login from './Login'

export default class App extends React.Component {
  render() {
    return (
      <Router>
        <div>
          <Route exact path='/login' component={Login} />
        </div>
      </Router>
    )
  }
}

Dans Login.js:

import React, {PropTypes} from 'react'

export default class Login extends React.Component {
  constructor(props) {
    super(props)
    this.handleLogin = this.handleLogin.bind(this)
  }

  handleLogin(event) {
    event.preventDefault()
    // do some login logic here, and if successful:
    this.props.history.Push(`/mypath`)
  }

  render() {
    return (
      <div>
        <form onSubmit={this.handleLogin}>
          <input type='submit' value='Login' />
        </form>
      </div>
    )
  }
}
36
Harlan T Wood

Dans le passé, vous utilisiez peut-être browserHistory pour indiquer un nouveau chemin. Cela ne fonctionnera pas avec react-router V4. Au lieu de cela, vous devez utiliser la méthode context de React et la méthode router de transitionTo.

Voici un exemple simple:

import React from 'react';

class NavigateNext extends React.Component {
  constructor() {
    super();
    this.navigateProgramatically = this.navigateProgramatically.bind(this);
  }

  navigateProgramatically(e) {
    e.preventDefault();

    this.context.router.transitionTo(e.target.href)
  }

  render() {
    return (
      <Link to={"/next-page"}
            onClick={this.navigateProgramatically}
      >Continue</Link>
    );
  }
}

NavigateNext.contextTypes = {
  router: React.PropTypes.object
};

transitionTo n'est qu'une des méthodes disponibles router. L'objet router contient également blockTransitions(getPromptMessage), createHref(to) et replaceWith(loc) qui méritent d'être extraites.

Voici tutoriel officiel react-router qui mentionne la méthode ci-dessus. Si vous voulez en savoir plus sur l'utilisation de react de context, consultez le docs .

19
spik3s

Je n'ai pas assez de réputation pour commenter, mais pour répondre à la question de @ singularity, vous devez inclure les propriétés de contexte que vous souhaitez rendre disponibles sur la propriété 'contextTypes static de la classe de composants.

De the React docs sur context :

Si contextTypes n'est pas défini, le contexte sera un objet vide.

Dans ce cas:

class NavigateNext extends React.Component {

  // ...

  static contextTypes = {
    router: PropTypes.object
  }

  // ...

}

Contrairement à propTypes, contextTypes fait en sorte que React se comporte différemment et ne concerne pas uniquement la vérification de type.

13
Jake Wisse

En utilisant withRouter , les propriétés du routeur seront ajoutées à votre composant. Vous pourrez alors accéder à history et utiliser Push comme vous l'avez fait avec v3:

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

class Form extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      input: '',
    };

    this._submit = this._submit.bind(this);
  }

  render() {
    return (
      <form onSubmit={this._submit}>
        <input type="text" onChange={(event) => this.setState({input: event.target.value})}/>

        <button type="submit">Submit</button>
      </form>
    );
  }

  _submit(event) {
    event.preventDefault();

    this.props.history.Push(`/theUrlYouWantToGoTo`);
  }
}

export default withRouter(Form);
9
Gokhan Sari

la version bêta de react-router v4 est publiée et l’API a légèrement changé. Au lieu de this.context.router.transitionTo(e.target.href) Do, this.context.router.Push(e.target.href) si vous utilisez la dernière version.

Lien vers le nouveau document: https://reacttraining.com/react-router/#context.router

6
Moinul Hossain

Si vous devez naviguer en dehors d'un composant à un emplacement que vous ne pouvez pas transmettre à l'objet d'historique à partir d'un composant similaire à celui que vous utiliseriez avec browserHistory dans les versions antérieures, vous pouvez procéder comme suit.

Tout d'abord créer un module d'histoire

History.js:

import createBrowserHistory from 'history/createBrowserHistory'

export default createBrowserHistory();

Ensuite, lorsque vous déclarez le routeur, assurez-vous d'importer le routeur à partir de react-router et non de react-router-dom (qui est juste un wrapper pour réagir à la version de routeur mais crée automatiquement un objet d'historique) et transmettez le module d'historique que vous venez de créer.

Root.js (ou où que vous fassiez cela):

import Router from 'react-router/Router'
import history from './history'

...

class Root extends Component{
  render() {
    return (
      <Router history={history}>
        ...
      </Router>
    );
  }
}

Désormais, votre application utilisera l’historique créé personnalisé que vous avez créé. Vous pouvez maintenant importer ce module d’historique n’importe où et simplement faire history.replace, etc. comme vous le feriez avec browserHistory dans le passé.

SomeModule.js:

import history from './history';

export default ()=>{
  // redirecting to login page using history without having to pass it in 
  // from a component
  history.replace('/login')
}

Bien sûr, ce n'est pas la méthode recommandée, car utiliser browserHistory dans les anciennes versions n'était pas recommandé car des fonctionnalités telles que le rendu côté serveur ne fonctionneraient pas, mais si vous ne vous en souciez pas, cela peut souvent être la bonne solution.

Un avantage supplémentaire à cela est que vous pouvez augmenter l'objet historique aux paramètres de chaîne de requête analysés, comme ceci par exemple:

import createBrowserHistory from 'history/createBrowserHistory'
import queryString from 'query-string';

const history = createBrowserHistory();

history.location.query = queryString.parse(history.location.search);

history.listen(() => {
  history.location.query = queryString.parse(history.location.search);
});

export default history;
6
Zaptree

Si vous avez besoin d'accéder à l'historique en dehors de composants (par exemple, dans redux , des actions ) react-router a publié sa solution d'origine here .

Fondamentalement, vous devez créer votre propre objet history :

import { createBrowserHistory } from 'history';

const history = createBrowserHistory();

Et passez le à votre routeur:

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

ReactDOM.render((
  <Router history={history}> // <<-- the history object
    <App/>
  </Router>
), document.getElementById('root'))

Remarque: vous devez utiliser un routeur standard à la place de BrowserRouter ou HashRouter ici !

Si vous exportez le history maintenant, vous pouvez le travailler n’importe où:

import history from './history';

history.Push('/home');
5
patotoma

J'ai trouvé en utilisant state, un opérateur ternaire et <Redirect> fonctionnait mieux. Je pense que c’est aussi la méthode préférée car elle se rapproche le plus de la configuration de la v4.

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 clickhandler ()

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

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

1
jar0m1r

utilisez withRouter :

import React, { PropTypes } from 'react'
import { withRouter } from 'react-router'

// A simple component that shows the pathname of the current location
class ShowTheLocation extends React.Component {
  static propTypes = {
    match: PropTypes.object.isRequired,
    location: PropTypes.object.isRequired,
    history: PropTypes.object.isRequired
  }

  render() {
    const { match, location, history } = this.props

    return (
      <div>You are now at {location.pathname}</div>
    )
  }
}

// Create a new component that is "connected" (to borrow redux
// terminology) to the router.
const ShowTheLocationWithRouter = withRouter(ShowTheLocation)
1
Tomasz Mularczyk

C'est vraiment difficile avec react-router. Aucune des options n'est simple. this.props.history m'a donné undefined. Mais

window.location='/mypath/';

a travaillé pour moi dans version 5.0.0. Je ne sais pas si c'est la bonne méthode.

0