0

I have a weird timing issue where React useLocation().pathname and history.location.pathname are NOT in sync, which leads to a wrong app re-rendering.

App logic: there are two routes available if the user is logged in: "/dashboard" and "/forbidden". The app initialisation navigates to "/dashboard" and then logs the user in. So I expect the "forbidden" component not to be rendered, when I access the app with this route, but to be redirected to the dashboard. However, in the console, the second app rendering after the login still delivers useLocation().pathname = "/forbidden", whereas history is correct. Which triggers the rendering of the "forbidden" component instead of the "dashboard".

I attached a sandbox where the issue is reproducable: https://codesandbox.io/s/laughing-stitch-y3cwvd?file=/src/App.js If you type the URL "/forbidden", you will see three console outputs. Why the pathnames are different in the second rendering?

I use following libraries: "react": "18.2.0" "react-dom": "18.2.0" "react-router": "6.10.0" "react-router-dom": "6.10.0" "react-router-redux": "4.0.8" "redux-first-history": "5.1.1" "history": "5.3.0"

Please help. I am breaking my head since two days on this and do not know if there is some library incompatibility or is it me doing something really stupid.

I was expecting the "forbidden" component not to be rendered at all. In the real app, I want to prevent the user from accidentally accessing an existing route, because it might require some special app state which is not loaded yet, which leads to unexpected errors.

miestr
  • 1
  • Just use the `location` object, `history` is mutable. What are you trying to do though? – Drew Reese Aug 28 '23 at 20:06
  • I want the app to render "/dashboard" after login, regardless of what the user typed in the URL. Though the app changes the URL to "/dashboard", it still re-renders the "forbidden" component once, before rendering dasboard. I do not use explicitely location or history anywhere - it is solely for creating console output. The setup of the redux-first-history is from the official documentation https://github.com/salvoravida/redux-first-history – miestr Aug 28 '23 at 20:31
  • Are you just trying to implement [protected routes](https://stackoverflow.com/a/66289280/8690857)? – Drew Reese Aug 28 '23 at 20:35
  • Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking. – Community Aug 29 '23 at 01:07
  • Both routes are only available if the user is logged in - if that is what you mean with protected routes. I want the app the render the /dashboard route after the login. But currently, the app triggers the rendering of /forbidden route, although the brower URL is /dashboard. To put it simple, if the user is on some protected route and refreshes the screen, I want the app to redirect to /dashboard. Without re-rendering of the protected route. – miestr Aug 29 '23 at 11:22
  • There's basically a "race condition" between when the `isLoggedIn` state is updated in the store and when the `push` action/navigation to `"/dashboard"` is effected in the router. If you add a delay between the two actions, e.g. `yield delay(0);`, you will likely see the log output you are expecting, e.g. it gives some "time" for one action to complete and React to rerender. The `history` object is mutable and isn't necessarily coupled to the React component lifecycle, so it's not a good source of truth for what the Router is rendering. Stick to using the `location` object via `useLocation`. – Drew Reese Aug 30 '23 at 15:23
  • Thank you very much for the explanation. Yes, the small delay helps. I thought there might be some issue within libraries that I use, as I never faced this issue wirh react-router before. Thanks again! – miestr Aug 31 '23 at 07:16

0 Answers0