Using navigate in useEffect leads to false routing
1. I navigate via a
<Link> to the /about page.
2. The component of the /about page has a useEffect which executes navigate function.
3. The navigate only applies an id query param, not more.
4. Expect: I would expect the final path to be /about?id=1234
5. Actual: The router navigates back to the home route / I'm coming from and applies the id=1234 query param there instead.
I created a repo with a reproduction and some additional notes in the README.
Reproduction: https://github.com/lukaskoeller/tanstack-react-router-useEffect-navigate-reproduction
I'm not sure if it's something I do wrong or rather a library bug, that's why I'm asking here first. Anybody that can help?9 Replies
rival-blackOP•17mo ago
E.g. when I set a timeout, it is working as expected. So I would assume the useEffect just runs too early when the navigation in the lib is not yet done?
ratty-blush•17mo ago
this most likely is a bug in router
ratty-blush•17mo ago
hopefully it was fixed now in https://github.com/TanStack/router/releases/tag/v1.45.5
GitHub
Release v1.45.5 · TanStack/router
Version 1.45.5 - 7/18/24, 6:52 PM
Changes
Fix
react-router: use current matches for fromMatches and only build new matches when location overridden (#1968) (99f7352) by Christopher Horobin
Test
...
ratty-blush•17mo ago
can you please try it out ?
rival-blackOP•17mo ago
Yes this fixed it! Brillian. Thanks a lo @Manuel Schiller
Heads up. A very similar problem happened in our production app again. This time, the router wouldn't navigate back to the "old" page but just wouldn't add the search params.
See the affected code using v1.45.8 here:
data here related to a useQuery. After removing the loader from the page it worked for the inital load. That means when the useEffect was executed after querying necessary data. It wouldn't work with cached data after returning to the dashboard. The current dirty workaround is a setTimeout.
I'm currently trying to reproduce the issue in this repo: https://github.com/lukaskoeller/tanstack-react-router-useEffect-navigate-reproduction. Yet I couldn't reproduce it but will let you know once I could
Overall the behavior in our app is really weird. Now I experienced search params for /benchmark are applied for other pages like /calculator. Also removing certain components and adding them suddently made the navigation as in the code above work.afraid-scarlet•17mo ago
Shouldn't you be cleaning up the setTimeout here? If not, across renders an outdated setTimeout could fire that'd cause old navigations to be fired.
rival-blackOP•17mo ago
yeah you're right. That should be fixed. Nonetheless, the last hours I'm trying to see what is causing the buggy behavior with search params in our app, I removed the
setTimeout
@Manuel Schiller @Sean Cassiere
Ok, at least one thing I was able to reproduce now. See reproducer. https://github.com/lukaskoeller/tanstack-react-router-useEffect-navigate-reproduction
The issue appears when two useEffect are executed shortly after each other. The time the second useEffect executes the navigate (see example below), the old params are still empty ({}) although the navigate of the useEffect was executed first and applied firstId. Thus, expected would be that the old of the navigate running shortly after is not empty ({}) but holds the firstId ({ firstId: 1337 }).
Now that I'm thinking about it, it is probably because the Promise of the first navigate hasn't resolved at the time the second navigate fires 🤔ratty-blush•17mo ago
yes, most likely. why do you have two useEffect that both navigate independently from each other ?
rival-blackOP•17mo ago
The other
useEffect lives in another component and is executed as soon as certain params are available which triggers isLoading of another useQuery
There's another issue with default search params. See reproducer: https://github.com/lukaskoeller/tanstack-react-router-useEffect-navigate-reproduction?tab=readme-ov-file#reproduction-2
Given the following validateSearch:
when you navigate the page, useSearch returns the default values, but they are not attached to the URL. That only happens when you reload the page. I would expect search params in the URL anytime when params are returned via useSearch
Turns out there's already an open github issue for that: https://github.com/TanStack/router/issues/1184
Created a github issue for this one: https://github.com/TanStack/router/issues/2028