2

I have a sidebar menu to change the page

I found that the page will not trigger re-render if I clicked the menu item that is current path.

(e.g. current path is /user and click the same path /user )

when entering the page it will call useEffect to get the data, but i want to click the same link again to reload the data instead of reloading the page

I have the following React router.

 <Routes>
   <Route path="" element={<MainLayout />}>
     <Route path="/user" element={<User />} />
     <Route path="/contact" element={<Contact />} />
     <Route exact path="/" element={<Login />} />
   </Route>
</Routes>

MainLayout.jsx

<Layout>
      <Sidebar />
      <Layout>
        <Header></Header>

        <Content >
          <Outlet />
        </Content>

        <Footer >
           Sorftware
        </Footer>
      </Layout>
</Layout>

Sidebar.jsx

<Menu>
  <Menu.Item key="users" >
     <Link to="/user">User</Link>
  </Menu.Item>
</Menu>

*UPDATE : I removed index.js and CustomRouter.jsx because it doesn't seem to be related to my question

  • If you're using react-router's `Link` component you can [specify the `reloadDocument` prop](https://stackoverflow.com/a/73415351/21146235). There's a few other options listed on that page too. – motto Mar 02 '23 at 07:47
  • that causes the page to be reloaded, but I just want it to be triggered to call the data again – phu.duongquoc Mar 02 '23 at 07:51
  • What specific version of `react-router` are you using? It looks like you are mixing v5 and v6 a bit. Can you [edit] to include all the relevant code you are working with, i.e. the nav/links/etc, as part of a more complete [mcve]? – Drew Reese Mar 02 '23 at 07:51
  • i'm using `react-router-dom: v6.6.2`, – phu.duongquoc Mar 02 '23 at 07:52
  • I see. RRDv6 `Route` components don't have a `component` prop. Use the `element` prop and pass JSX, e.g. `element={}`. – Drew Reese Mar 02 '23 at 07:53
  • @phu.duongquoc Among the many options listed on that page is [adding a random key to the route renderer/element](https://stackoverflow.com/a/51057553/21146235). You could also add a random extra prop to the link. – motto Mar 02 '23 at 07:54
  • @DrewReese I used as you said but it didn't work – phu.duongquoc Mar 02 '23 at 07:59

1 Answers1

2

If you are looking for a way to trigger a route component rerender upon clicking a Link then I'd suggest using a navigation action that passes a different object, i.e. use a hash or pass some additional state, that is different on each click of the link.

Example:

import { Link, useNavigate } from "react-router-dom";
import { nanoid } from "nanoid";

...

const navigate = useNavigate();

...

<Link
  to="/user"
  onClick={(e) => {
    e.preventDefault();
    navigate("/user", { state: nanoid() });
  }}
>
  User
</Link>

The example here uses the Link component's to prop to provide a valid target and provide all the accessibility components. Then an onClick handler is attached to prevent the default link action from occurring so we can pass some additional state payload that is different and random each time it is invoked.

You could use this passed state as a useEffect hook dependency if you like.

const { state } = useLocation();

useEffect(() => {
  // run side-effect
}, [state]);

Demo

Edit how-to-re-render-the-component-on-same-routing-path-link-to-reactjs

Drew Reese
  • 165,259
  • 14
  • 153
  • 181
  • Thanks for the help but i tried this and it still does not work, maybe i have not provided enough data, i have updated the code with more detail, maybe my code it's different from your example – phu.duongquoc Mar 02 '23 at 09:05
  • @phu.duongquoc Your code doesn't seem too terribly different. Basically all you need is some routes and the `Link` to navigate to them. What exactly wasn't working on your end? – Drew Reese Mar 02 '23 at 09:33
  • I did it the way you pointed and what doesn't work here is when i click on the `Link` it doesn't change anything, i have checked through console.log and the tab network in `User` but everything is still the same, api is not called, component is not rendered – phu.duongquoc Mar 02 '23 at 09:40
  • @phu.duongquoc Sorry, rookie mistake, I was passing state the RRDv5 way instead of the v6 way where `state` is passed in the `options` object of `navigate`. Please check now. – Drew Reese Mar 02 '23 at 09:43
  • it worked, but I wonder if this is optimal and if there is a more efficient or compact way – phu.duongquoc Mar 02 '23 at 10:23
  • @phu.duongquoc I don't think it gets much more minimal than this. Navigating to a route you are already on is generally a non-op, so you have to do *something* to make it a unique transition. – Drew Reese Mar 02 '23 at 10:27
  • Do you have a better way to do it? because I'm a newbie, so there are many unknowns, you can give me keyword or link or something to learn about it, if it's good and convenient for maintenance later I will be happy to change the way – phu.duongquoc Mar 02 '23 at 10:43
  • @phu.duongquoc I'm not sure I follow. What I've suggested in my answer is about the best way I can think of to go about it. It's what I'd use in my code if I had the same/similar use case as what you ask about. It's clear, succinct, readable, and maintainable. You could abstract it into a custom link component if you like. That's about the only improvement I see here that this specific code. – Drew Reese Mar 03 '23 at 10:07