React and antd: Router doesn't re-render components

回眸只為那壹抹淺笑 提交于 2021-01-07 02:41:46

问题


I have a simple web page with login and search pages. I also have a navbar at the top to allow for switching between the two. The basic App.js looks as follows:

const history = createBrowserHistory();

function App() {
    return (
        <Router history={history}>
            <CustomLayout>
                <Switch>
                    <BaseRouter/>
                </Switch>
            </CustomLayout>
        </Router>
    );
}

export default App;

Now, the BaseRouter and CustomLayout are just

const BaseRouter = () => (
    <div>
        <Route exact path={"/list"} component={ItemsList}/>
        <Route path={"/login"} component={LoginForm}/>
    </div>
);

export default BaseRouter;

and

const CustomLayout = ({children}) => {
    return(
        <>
        <Navbar/>
        {children}
        </>
    );
}

export default CustomLayout;

Now, the navbar looks like this

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

Let's keep components simple:

const Login = () => {
    return (
        <div>
            login
        </div>
    );
}

export default Login

const List = () => {
    return (
        <div>
            list
        </div>
    );
}

export default List

Now the problem is that when I click on links in the navbar, React doesn't re-render components even though the route changes. I've seen hundreds of answers on SO but I still can't figure it out.
NOTE
It is important for me to avoid refreshing or reloading the page.
EDIT
Strangely enough, when I change Router to BrowserRotuer it works fine, but I can't use my own history then.


回答1:


why don't you use BrowserRouter from react-router-dom package.

  • App.js:- use BrowserRouter from react-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:- import Route from react-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

then if you want to use 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>
    </>
  )
}



回答2:


Change your BaseRouter from this :

const BaseRouter = () => (
    <div>
        <Route exact path={"/list"} component={ItemsList}/>
        <Route path={"/login"} component={LoginForm}/>
    </div>
);

export default BaseRouter;

To this :

const BaseRouter = () => (
    <div>
        <Route exact path="/list" component={ItemsList}/>
        <Route path="/login" component={LoginForm}/>
    </div>
);

export default BaseRouter;



回答3:


I believe you cannot have the div inside the switch. You're not exposing the Route components to your switch statement.

Therefore, your url changes because your Navbar makes it change but your switch doesn't know what to do.

Try changing your base router to this:

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;



回答4:


Router is low-level and expects you to manage things. BrowserRouter already syncs with HTML5 history. If you want Router, I think you have to manage the syncing yourself (e.g. <Link onClick={() => history.push(href)}>) or listen to history for change detection. See Detect Route Change with react-router



来源:https://stackoverflow.com/questions/64820799/react-and-antd-router-doesnt-re-render-components

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!