J'ai une page Web simple avec des pages de connexion et de recherche. J'ai également une barre de navigation en haut pour permettre de basculer entre les deux. Le App.js
base se App.js
comme suit:
const Login = () => { return ( <div> login </div> ); } export default Login const List = () => { return ( <div> list </div> ); } export default List
Maintenant, le BaseRouter
et le CustomLayout
sont plus que
import React from "react"; import {Menu} from 'antd'; import {Link} from "react-router-dom"; const Navbar = () => { return ( <div> <Menu mode="horizontal" theme={"dark"}> <Menu.Item key="list"> <Link to={"/list"}>List</Link> </Menu.Item> <Menu.Item key={"login"}> <Link to={"/login"}>Sign in</Link> </Menu.Item> </Menu> </div> ); } export default Navbar
et
const CustomLayout = ({children}) => { return( <> <Navbar/> {children} </> ); } export default CustomLayout;
Maintenant, la barre de navigation ressemble à ceci
const BaseRouter = () => ( <div> <Route exact path={"/list"} component={ItemsList}/> <Route path={"/login"} component={LoginForm}/> </div> ); export default BaseRouter;
Gardons les composants simples:
const history = createBrowserHistory(); function App() { return ( <Router history={history}> <CustomLayout> <Switch> <BaseRouter/> </Switch> </CustomLayout> </Router> ); } export default App;
Maintenant, le problème est que lorsque je clique sur des liens dans la barre de navigation, React ne restitue pas les composants même si l'itinéraire change. J'ai vu des centaines de réponses sur SO mais je n'arrive toujours pas à comprendre.
REMARQUE
Il est important pour moi d'éviter d'actualiser ou de recharger la page.
ÉDITER
Curieusement, lorsque je change Router
en BrowserRotuer
cela fonctionne bien, mais je ne peux pas utiliser ma propre histoire.
4 Réponses :
Changez votre BaseRouter
partir de ceci:
const BaseRouter = () => ( <div> <Route exact path="/list" component={ItemsList}/> <Route path="/login" component={LoginForm}/> </div> ); export default BaseRouter;
Pour ça :
const BaseRouter = () => ( <div> <Route exact path={"/list"} component={ItemsList}/> <Route path={"/login"} component={LoginForm}/> </div> ); export default BaseRouter;
Non, je suis désolé, cela n'a rien changé
Je crois que vous ne pouvez pas avoir le div à l'intérieur du commutateur. Vous n'exposez pas les composants Route à votre instruction switch.
Par conséquent, votre URL change parce que votre Navbar la fait changer, mais votre commutateur ne sait pas quoi faire.
Essayez de changer votre routeur de base pour ceci:
const BaseRouter = () => ( <Switch> <Route exact path={"/list"} component={ItemsList}/> <Route path={"/login"} component={LoginForm}/> </Switch> ); export default BaseRouter;
const history = createBrowserHistory(); function App() { return ( <Router history={history}> <CustomLayout> <BaseRouter/> </CustomLayout> </Router> ); } export default App;
Non, je suis désolé, cela n'a rien changé
Router
est de bas niveau et attend de vous que vous gériez les choses. BrowserRouter
synchronise déjà avec l'historique HTML5. Si vous voulez un Router
, je pense que vous devez gérer vous-même la synchronisation (par exemple <Link onClick={() => history.push(href)}>)
ou écouter l'historique pour détecter les changements. Voir Détecter le changement d'itinéraire avec react-router
Cela explique-t-il pourquoi je recevais un avertissement: You cannot change the history of Router
C'est vrai, mais il existe des moyens beaucoup plus simples, par exemple useLocation
hook
pourquoi n'utilisez-vous pas BrowserRouter
du BrowserRouter
react-router-dom
.
App.js
: - utilisez BrowserRouter
de BrowserRouter
react-router-dom
import { useHistory } from 'react-router-dom' const testFunctionComponent = () => { const history = useHistory() const handleClick = (urlPath) => { // you can do history.push(urlPath) // to go anywhere } return ( <> <button onClick={() => handleClick('/anypath')}>Click Me!<button> </> ) }
BaseRouter.js
: - importer une Route
depuis BaseRouter.js
react-router-dom
import React from "react"; import {Menu} from 'antd'; import {Link} from "react-router-dom"; const Navbar = () => { return ( <div> <Menu mode="horizontal" theme={"dark"}> <Menu.Item key={"list"}> <Link to="/list">List</Link> </Menu.Item> <Menu.Item key={"login"}> <Link to="/login">Sign in</Link> </Menu.Item> </Menu> </div> ); } export default Navbar
Navbar.js
: -import { Route } from 'react-router-dom' const BaseRouter = () => ( <div> <Route exact path="/list" component={ItemsList}/> <Route path="/login" component={LoginForm}/> </div> ); export default BaseRouter;
alors si vous voulez utiliser l' history
: -
import { BrowserRouter as Router, Switch } from 'react-router-dom' function App() { return ( <Router> <CustomLayout> <Switch> <BaseRouter/> </Switch> </CustomLayout> </Router> ); } export default App;
À quiconque lit ceci: c'est le moyen le plus simple. J'ai également constaté que si vous utilisez BrowserRouter
vous pouvez appeler props.history.push()
dans le composant de votre props.history.push()
.
Oui. C'est vrai pour tous les composants étant les enfants sous le BrowserRouter
.