React e antd: il router non esegue nuovamente il rendering dei componenti
Ho una semplice pagina web con login e pagine di ricerca. Ho anche una barra di navigazione in alto per consentire il passaggio tra i due. L' App.jsaspetto di base è il seguente:
const history = createBrowserHistory();
function App() {
return (
<Router history={history}>
<CustomLayout>
<Switch>
<BaseRouter/>
</Switch>
</CustomLayout>
</Router>
);
}
export default App;
Ora, BaseRoutere CustomLayoutsono solo
const BaseRouter = () => (
<div>
<Route exact path={"/list"} component={ItemsList}/>
<Route path={"/login"} component={LoginForm}/>
</div>
);
export default BaseRouter;
e
const CustomLayout = ({children}) => {
return(
<>
<Navbar/>
{children}
</>
);
}
export default CustomLayout;
Ora, la barra di navigazione ha questo aspetto
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
Manteniamo i componenti semplici:
const Login = () => {
return (
<div>
login
</div>
);
}
export default Login
const List = () => {
return (
<div>
list
</div>
);
}
export default List
Il problema è che quando clicco sui collegamenti nella barra di navigazione, React non esegue nuovamente il rendering dei componenti anche se il percorso cambia. Ho visto centinaia di risposte su SO ma ancora non riesco a capirlo.
NOTA
È importante per me evitare di aggiornare o ricaricare la pagina.
EDIT
Stranamente, quando cambio Routera BrowserRotuerfunziona bene, ma allora non posso usare la mia storia.
Risposte
perché non usi BrowserRouterfrom react-router-dompackage.
App.js: - utilizzareBrowserRouterdareact-router-dom
import { BrowserRouter as Router, Switch } from 'react-router-dom'
function App() {
return (
<Router>
<CustomLayout>
<Switch>
<BaseRouter/>
</Switch>
</CustomLayout>
</Router>
);
}
export default App;
BaseRouter.js: - importaRoutedareact-router-dom
import { Route } from 'react-router-dom'
const BaseRouter = () => (
<div>
<Route exact path="/list" component={ItemsList}/>
<Route path="/login" component={LoginForm}/>
</div>
);
export default BaseRouter;
Navbar.js: -
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
allora se vuoi usare history: -
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>
</>
)
}
Cambia il tuo BaseRouterda questo:
const BaseRouter = () => (
<div>
<Route exact path={"/list"} component={ItemsList}/>
<Route path={"/login"} component={LoginForm}/>
</div>
);
export default BaseRouter;
A questa :
const BaseRouter = () => (
<div>
<Route exact path="/list" component={ItemsList}/>
<Route path="/login" component={LoginForm}/>
</div>
);
export default BaseRouter;
Credo che tu non possa avere il div all'interno dell'interruttore. Non stai esponendo i componenti Route alla tua istruzione switch.
Pertanto, il tuo URL cambia perché il tuo Navbar lo fa cambiare ma il tuo interruttore non sa cosa fare.
Prova a cambiare il tuo router di base in questo:
const history = createBrowserHistory();
function App() {
return (
<Router history={history}>
<CustomLayout>
<BaseRouter/>
</CustomLayout>
</Router>
);
}
export default App;
const BaseRouter = () => (
<Switch>
<Route exact path={"/list"} component={ItemsList}/>
<Route path={"/login"} component={LoginForm}/>
</Switch>
);
export default BaseRouter;
Routerè di basso livello e si aspetta che tu gestisca le cose. BrowserRoutersi sincronizza già con la cronologia HTML5. Se vuoi Router, penso che tu debba gestire tu stesso la sincronizzazione (ad esempio <Link onClick={() => history.push(href)}>)o ascoltare la cronologia per il rilevamento delle modifiche. Vedi Rileva cambio di percorso con il router reattivo