React e antd: il router non esegue nuovamente il rendering dei componenti

Nov 13 2020

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

1 lala Nov 13 2020 at 13:51

perché non usi BrowserRouterfrom react-router-dompackage.

  • App.js: - utilizzare BrowserRouterdareact-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: - importa Routedareact-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>
    </>
  )
}
GayatriDipali Nov 13 2020 at 12:27

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;
ThalesKenne Nov 13 2020 at 12:35

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;
PhilipRamirez Nov 13 2020 at 13:32

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