3
votes

Le composant n'est pas rendu après history.push ()

Sur un clic de bouton, j'obtiens l'URL modifiée en faisant history.push ()

import React, {Component} from 'react'  
import {BrowserRouter, Router, Route, Switch, withRouter} from 'react-router-dom'  
import createHistory from 'history/createBrowserHistory'  

import Home from './pages/home'  
import ViewFile from './pages/view-file'  

const history = createHistory()

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

      render() {
      return (
          <Router history={history}>
              <Switch>
                  <Route exact path={'/'} component={Home}/>
                  <Route path={'/share/:id'} component={ViewFile}/>
              </Switch>
          </Router>
      )
  }
}

export default App 

et en espérant le composant mentionné dans la Route pour cette URL serait rendu mais cela ne se produit pas. Cependant, lors de l'actualisation, ce composant est rendu comme prévu. Mais je ne comprends pas pourquoi il ne s'affiche pas dès que l'URL change. J'ai essayé d'encapsuler le composant dans withRouter .

import React, {Component} from 'react'  
import {BrowserRouter, Router, Route, Switch, withRouter} from 'react-router-dom'  
import createHistory from 'history/createBrowserHistory'  

import Home from './pages/home'  
import ViewFile from './pages/view-file'  

const history = createHistory()

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

      render() {
      return (
          <BrowserRouter>
              <Switch>
                  <Route exact path={'/'} component={Home}/>
                  <Route path={'/share/:id'} component={withRouter(ViewFile)}/>
              </Switch>
          </BrowserRouter>
      )
  }
}

export default App 

ainsi que le passage de l ' historique dans Router , ce que je pense identique à l'utilisation de BrowserRouter .

import createHistory from 'history/createBrowserHistory'  
const history = createHistory()  
.  
. some code  
.  
history.push(`/share/${objectId}`)

mais pas de chance avec ça. Quelqu'un peut-il expliquer pourquoi cela se produit?
PS J'ai parcouru les réponses ici mais ils n'ont pas aidé


3 commentaires

Pouvez-vous coller plus de code concernant l'endroit où vous appelez: history.push ( / share / $ {objectId} )


quelle version du routeur de réaction?


@ Sujit.WarrierIl est 4.3.1


4 Réponses :


5
votes

Vous créez un nouvel historique chaque fois que vous appelez createHistory () . Si vous utilisez react-router-dom , vous pouvez simplement utiliser le HOC withRouter qui fournira l'objet history au composant via un prop . Vous utiliserez ensuite history.push ('/') , ou si c'est dans un composant de classe , this.props.history.push ('/' ) et ainsi de suite.

Exemple de travail : https: // codesandbox .io / s / p694ln9j0

routes (définissez l'historique dans routes )

XXX

components / Header.js (nous voulons accéder à l'historique , cependant, parfois nous devons utiliser withRouter code > parce que des composants tels que Header ne résident pas dans un HOC, donc il ne connaît pas notre routage) p >

import React from "react";
import { BrowserRouter, Route, Switch } from "react-router-dom";
import Header from "../components/Header";
import Home from "../components/Home";
import About from "../components/About";
import Contact from "../components/Contact";
import Notfound from "../components/Notfound";
import ScrollIntoView from "../components/ScrollIntoView";

export default () => (
  <BrowserRouter>
    <div>
      <ScrollIntoView>
        <Header />
        <Switch>
          <Route exact path="/" component={Home} />
          <Route path="/about" component={About} />
          <Route path="/contact" component={Contact} />
          <Route component={Notfound} />
        </Switch>
        <Header />
      </ScrollIntoView>
    </div>
  </BrowserRouter>
);

components / Home.js (un composant comme Home est conscient du routage et possède l ' historique code > objet déjà transmis via le HOC, donc withRouter n'est pas requis)

import React from "react";

const Home = ({ history }) => (
  <div className="container">
    <button
      className="uk-button uk-button-danger"
      onClick={() => history.push("/notfound")}
    >
      Not Found
    </button>
    <p>
      ...
    </p>
  </div>
);

export default Home;

Même concept a s ci-dessus, cependant, si vous ne souhaitez pas utiliser withRouter , vous pouvez simplement créer une instance historique qui sera partagée entre vos composants qui en ont besoin. Vous allez importer cette instance historique et naviguer avec history.push ('/'); et ainsi de suite.

Exemple de travail : https://codesandbox.io/s/5ymj657k1k

historique (définir historique dans son propre fichier)

import React from "react";
import history from "../history";

const Header = () => (
  <header>
    <nav style={{ textAlign: "center" }}>
      <ul style={{ listStyleType: "none" }}>
        <li style={{ display: "inline", marginRight: 20 }}>
          <button onClick={() => history.push("/")}>Home</button>
        </li>
        <li style={{ display: "inline", marginRight: 20 }}>
          <button onClick={() => history.push("/about")}>About</button>
        </li>
        <li style={{ display: "inline", marginRight: 20 }}>
          <button onClick={() => history.push("/contact")}>Contact</button>
        </li>
      </ul>
    </nav>
  </header>
);

export default Header;

routes strong> (importez l'historique dans itinéraires)

import React from "react";
import { Router, Route, Switch } from "react-router-dom";
import Header from "../components/Header";
import Home from "../components/Home";
import About from "../components/About";
import Contact from "../components/Contact";
import ScrollIntoView from "../components/ScrollIntoView";
import history from "../history";

export default () => (
  <Router history={history}>
    <div>
      <ScrollIntoView>
        <Header />
        <Switch>
          <Route exact path="/" component={Home} />
          <Route path="/about" component={About} />
          <Route path="/contact" component={Contact} />
        </Switch>
        <Header />
      </ScrollIntoView>
    </div>
  </Router>
);

composants / Header.js ( importer l'historique dans Header)

import { createBrowserHistory } from "history";

const history = createBrowserHistory();

export default history;

composants / Home.js (est toujours au courant de routage et a l'objet history déjà transmis via le HOC, donc importation de history code> n'est pas obligatoire, mais vous pouvez toujours l'importer si vous le souhaitez - ne déconstruisez pas l'historique dans les paramètres de fonction de Accueil ) p >

import React from "react";

const Home = ({ history }) => (
  <div className="container">
    <button
      className="uk-button uk-button-danger"
      onClick={() => history.push("/notfound")}
    >
      Not Found
    </button>
    <p>
      ...
    </p>
  </div>
);

export default Home;

Mais vous pensez peut-être, w À propos de BrowserRouter ? Eh bien, BrowserRouter a son propre objet interne history . On peut, encore une fois, utiliser withRouter pour accéder à son historique . Dans ce cas, nous n'avons même pas besoin de createHistory () du tout!

Exemple de travail : https://codesandbox.io/s/ko8pkzvx0o

routes

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

const Header = ({ history }) => (
  <header>
    <nav style={{ textAlign: "center" }}>
      <ul style={{ listStyleType: "none" }}>
        <li style={{ display: "inline", marginRight: 20 }}>
          <button onClick={() => history.push("/")}>Home</button>
        </li>
        <li style={{ display: "inline", marginRight: 20 }}>
          <button onClick={() => history.push("/about")}>About</button>
        </li>
        <li style={{ display: "inline", marginRight: 20 }}>
          <button onClick={() => history.push("/contact")}>Contact</button>
        </li>
      </ul>
    </nav>
  </header>
);

export default withRouter(Header);


7 commentaires

Merci beaucoup. J'ai perdu des heures hier à lire la documentation de React Router mais je n'ai pas beaucoup compris. Je pense que vous auriez dû écrire les documents.


Cela ne fonctionne pas, je ne sais pas pourquoi, j'utilise Router pas BrowserRouter mais tous mes composants ne sont pas rendus, l'URL change mais j'obtiens toujours le 404 composant d'itinéraire de secours.


@HassanAzzam Veuillez créer un MCVE , puis un posez une nouvelle question avec votre exemple de code.


C'est exactement le même code ci-dessus, et cela ne fonctionne pas. J'ai même essayé history.listen et il renvoie undefined lorsque je change d'itinéraires.


@HassanAzzam Il semble qu'ils aient abandonné la prise en charge de l'utilisation de votre propre objet d'historique dans la v5. Quand cela a été écrit, la v4.xx était la dernière, et en tant que telle, elle fonctionne comme prévu . Je vous encourage à vous éloigner de cette approche car il existe d'autres meilleures alternatives (comme utiliser BrowserRouter avec le hook useHistory ou accéder à l'historique avec le composant d'ordre supérieur withRouter si vous n'utilisez pas de hooks)


Ou ... si vous utilisez redux , utilisez connecté- react-router , qui vous permet de pousser ou remplacer des éléments de l'historique de n'importe où.


Oui, je sais, mais le problème est que je voulais l'utiliser en dehors d'un composant, et useHistory ne fonctionne qu'à l'intérieur d'un composant. Mais en tout cas merci pour la clarification que vous m'avez fait gagner beaucoup de temps.



2
votes

Quelques points:

1) Utilisez import {Router} depuis 'react-router-dom' plutôt que import {BrowserRouter as Router} depuis 'react-router-dom'

2) Créer une variable historique dans un fichier différent à savoir (peut être modifié) ../src/services/ history.js et le contenu doit être:

import React from 'react'
import history from '../services/history';

export default class VendorPage extends React.Component {

    loginUser = () => {
        if (<SOME_CONDITION>)
            history.push('/client')
    }

    render() {
        return (
            <h1>Welcome to Vendor Page....</h1>
        )
    }
}

Vous devrez installer le package react-history avant le npm install --save react-history

3) Importez l'historique dans le fichier principal et passez-le dans le composant Router.

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


class App extends React.Component {

    render() {
        return (
            <Router history={history}>
                <Switch>
                    <Route exact path='/' component={MainPage}></Route>
                    <Route exact path='/vendor' component={VendorPage}></Route>
                    <Route exact path='/client' component={ClientPage}></Route>
                </Switch>
            </Router>
        );
    }
}

export default App;

4) Maintenant, vous pouvez utiliser l'historique n'importe où dans les composants par

import { createBrowserHistory } from 'history';
const history = createBrowserHistory();
export default history;

J'espère que cela vous aidera ..

:)


2 commentaires

Je pense qu'il peut utiliser le hook useHistory () de react-router-dom , afin qu'il n'ait pas à installer une autre bibliothèque.


malheureusement cela ne semble plus fonctionner



6
votes

utilisez import {Router} au lieu de import {BrowserRouter as Router} . Parce que BrowserRouter ignore le prop d'historique.


2 commentaires

A fonctionné comme un charme. Merci beaucoup.


Hou la la! C'était ça! Tant d'heures à essayer de trouver ça! Le history.push () fonctionne exactement comme ça avec Router .



1
votes

Cela peut aider quelqu'un. Assurez-vous que la version du package history est compatible avec react-router-dom .

Cette combinaison n'a pas fonctionné pour moi:

historique: 5.0.0 avec react-router-dom: 5.2.0

Ce combo a fait :

historique: 4.10.1 avec react-router-dom 5.2.0


0 commentaires