web-dev-qa-db-fra.com

React-router v4 this.props.history.Push (...) ne fonctionne pas

J'essaie de router par programme en utilisant this.props.history.Push(..) mais cela ne semble pas fonctionner.

Voici le routeur: 

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

<Router>
 <Route path="/customers/" exact component={CustomersList} />
 <Route path="/customers/:id" exact component="{Customer} />
</Router>

Dans CustomerList, une liste de clients est rendue. En cliquant sur un client (li), l'application doit être acheminée vers le client:

import { withRouter } from 'react-router'

class Customers extends Component {
  static propTypes = {
    history: PropTypes.object.isRequired
  }

 handleCustomerClick(customer) {
   this.props.history.Push(`/customers/${customer.id}`);
 }

 render() {
   return(
    <ul>
      { this.props.customers.map((c) =>
        <li onClick={() => this.handleCustomerClick(c)} key={c.id}>
          {c.name}
        </li> 
    </ul>
  )

 }
}

//connect to redux to get customers

CustomersList = withRouter(CustomersList);
export default CustomersList;

Le code est partiel mais illustre parfaitement la situation… .. Ce qui se passe, c'est que la barre d'adresse du navigateur change en conséquence en history.Push (..), mais la vue ne se met pas à jour, le composant Client n'est pas rendu et CustomersList est toujours là. Des idées?

19
Andrea Ongaro

Je suis donc venu à cette question en espérant une réponse mais en vain. j'ai utilisé

const { history } = this.props;
history.Push("/thePath")

Dans le même projet et cela a fonctionné comme prévu . Après des expériences supplémentaires et quelques comparaisons et contrastes, j'ai réalisé que ce code ne fonctionnera pas s'il est appelé dans le composant imbriqué. Par conséquent, seul le composant de page rendu peut appeler cette fonction pour que celle-ci fonctionne correctement.

Trouver un bac à sable ici

  • histoire: v4.7.2 
  • réagir: v16.0.0 
  • react-dom: v16.0.0 
  • react-router-dom: v4.2.2
8
Delanyo Aborchie

Vous pouvez essayer de charger le composant enfant avec l'historique. pour ce faire, passez «l'histoire» à travers les accessoires. Quelque chose comme ca:

  return (
  <div>
    <Login history={this.props.history} />
    <br/>
    <Register/>
  </div>
)
3
Taha A.

On dirait une vieille question mais toujours d'actualité.

Je pense que c'est un problème de mise à jour bloqué .

Le problème principal est que la nouvelle URL (route) est supposée être rendue par le même composant (Costumers) que celui dans lequel vous vous trouvez actuellement (URL actuelle).

Donc, la solution est assez simple, créez l'URL de la fenêtre comme un accessoire, réagissez donc pour pouvoir détecter le changement de l'accessoire (donc le changement de l'URL), et agissez en conséquence.

Un cas d'utilisation Nice décrit dans le blog de réaction officiel appelé Recommandation: Composant totalement non contrôlé avec une clé .

Donc, la solution est de changer de render() { return( <ul>

to render() { return( <ul key={this.props.location.pathname}>

Ainsi, chaque fois que l'emplacement change par react-router, le composant est mis au rebut (par react) et un nouveau est lancé avec les bonnes valeurs (par react).

Oh, et passez la location en tant que prop au composant (Costumers) où la redirection aura lieu si elle n'est pas déjà passée.

J'espère que ça aide quelqu'un.

1
arcol

Pour moi (réagit-router v4, réagit v16), le problème était que j'avais le composant de navigation correct:

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

class MainMenu extends Component {

  render() {
    return (
            ...
            <NavLink to="/contact">Contact</NavLink>
            ...
    );
  }
}

export default withRouter(MainMenu);

Les deux utilisant soit 

to="/contact" 

ou 

OnClick={() => this.props.history.Push('/contact')}; 

Le comportement était toujours le même - l'URL dans le navigateur a changé mais des composants incorrects ont été générés, le routeur a été appelé avec le même ancien URL.

Le coupable était dans la définition du routeur. J'ai dû déplacer le composant MainMenu en tant qu'enfant du composant Router!

// wrong placement of the component that calls the router
<MainMenu history={this.props.history} />
<Router>
   <div>
     // this is the right place for the component!
     <MainMenu history={this.props.history} />
     <Route path="/" exact component={MainPage} />
     <Route path="/contact/" component={MainPage} />
   </div>
</Router>
0
Jan Matousek

Vous devez exporter le composant Clients et non le CustomerList.

    CustomersList = withRouter(Customers);
    export default CustomersList;
0

Ne pas utiliser avec le routeur.

handleSubmit(e){
   e.preventDefault();
   this.props.form.validateFieldsAndScroll((err,values)=>{
      if(!err){
        this.setState({
            visible:false
        });
        this.props.form.resetFields();
        console.log(values.username);
        const path = '/list/';
        this.props.history.Push(path);
      }
   })
}

Ça marche bien.

0
YangFang