-
Notifications
You must be signed in to change notification settings - Fork 26.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
revalidateTag and revalidatePath redirect to intercepting route when inside dynamic route #59796
Comments
Short potato-quality video of the bug: Screen.Recording.2023-12-20.at.16.31.10.mov |
Even weirder is if I add a |
We have the same problem: revalidating any (unrelated) route while on the intercepted route refreshes the route into its full-page version. We are also using next-intl and have all routes inside |
We have the same problem - calling |
is it fixed or not yet? when i call revalidatePath('/') from server action for opened modal ( intercepting route ) i get redirected to 404 |
Not as far as I'm aware. I'll update my reproduction to the latest version. I ended up just removing all usage of intercepting / parallel routes from my project because this feature is so unreliable. |
i guess parallel route is fixed with next update , but not the intercepting route , because when i open the modal and i call a server action then revalidatePath i get 404! |
I also have this issue. When I intercept a route and the modal page component is shown, if I have a server action in the modal, the background page will refresh, but no 404, it just loses all the background page elements, which is not the ideal situation... |
I just fixed my case by adding the same components into the default.tsx . It's confusing but I got it! |
Mind sharing an example of what's going in default.tsx? Thank you! |
I've updated my example reproduction with NextGram to the last version of Next.js, the issue is still present. Calling the revalidate functions from a server action while on an intercepted route reloads the page, seems like it causes the client router cache to be completely wiped. |
In essence, my default.tsx will be exactly the same as the page.tsx. Then if I have an intercepting route that opens another page as modal, and I call a server action inside the modal, the background which was page.tsx seems to call the default.tsx, which if you don't have it will give you the 404 error. So you either create an exact copy of page.tsx and call it default.tsx or you could simply create a default.tsx page returning null, but then the page will be blank after you call the server action. Still, I face another challenge. After calling the server action, I can see that my background page did not change after revalidatingPath("/"), however, if I close the modal to show the background page, it will still refresh the page, probably changing from the default.tsx to the page.tsx ... This behaviour doesn't occur, if I don't call the server action with revalidatePath on the modal. It's not a big deal, but this behaviour is still not the ideal one... Edit: Seems that this is because when I close the modal, I'm using router.back() and so it goes from default.tsx to page.tsx for some weird reason. I don't know how can I fix this. |
I've got a new solution, instead of using page.tsx and default.tsx, I've moved my components to layout.tsx, perhaps create a specific folder for your page, so that the layout only afects pages inside that folder. With this, the revalidatePath works inside the modal and doesn't break anything, also if you close the modal it will go back to the previous page without any refresh. Make sure to use next links with scroll={false} so that it won't scroll to the top when you open a page inside a modal! |
for me its reloading to 404 page because the intercepted route is nested in a group route i guess |
returning null after calling SA inside intercepted route is redirecting me to blank 404 page !! |
@samcx can ui please review this issue ? |
Anyone found a solution for this? |
The problem remains unresolved in the newly released |
Also interested in this. Am I correct that this is the same core problem as in #51714 (which I believe is the one being tracked, at least based on Zack's comment #60815 (comment)) |
My temporary solution is to open a modal using searchParams. For example you can use a link to change route to This way I'm still able to do the server actions and nothing breaks. Still, I'd love to use the intercepting modals as a hard refresh would lead to the normal route. |
They all seem related to me... the client side router cache gets blown away when revalidating, and so it forces a reload, which for this particular use case means reloading onto the intercepted route. My "workaround" is similar to @sim391calado -- just don't use these features yet until they are actually stable. I'm also using a similar approach decide when to show a modal. Definitely lost a lot of confidence in the product because of this, it feels like these features were rushed out without much testing, clearly no one is using them in serious production apps if these basic use cases don't work (submit a pop-up form on an internationalised app). |
@dcapinator I can confirm this is still an issue. @kahnclusions I understand this pain—our parallel/intercepting routes has received a ton of bug fixes, but there are still bugs such as this one. We are still looking to fix these very soon! 🙇🏼 |
Hello I really love this feature but I am experiencing this bug too |
Also I would love to use this for forms inside modals w/ parallel routes but the bug completely breaks it. |
What should I do to "refresh" parallel route modal data that was fetched on server? In this is my temporary fix: <Button
onClick={() => {
// * this is a hacky way I've implemented to handle the refetching of the server component data
const query = qs.stringify(
{
...Object.fromEntries(searchParams),
ts: Date.now(),
},
{ addQueryPrefix: true },
);
setTimeout(() => {
router.push(`${pathname}${query}`, { scroll: false });
}, 50);
router.back();
}}>
refresh
</Button> Only then the parallel route runs the awaited fetch call. |
Might be fixed by https://github.com/vercel/next.js/releases/tag/v14.2.0-canary.33, I haven't had the opportunity to test it. |
@Aldo-Garza Let us know if that push fixed the issue! |
@Aldo-Garza @samcx I have confirmed that with #63263, revalidating in a server action called by a client component with |
I tested it with the latest canary version and the bug persists. If I revalidate tag within a server action on form submission, the intercepting route (dialog) is refreshed and the route that is being intercepted is rendered. |
and once rendered is the modal is not in the root folder , instead in a group route then i get 404 error |
) ### What When calling `revalidatePath` or `revalidateTag` in a server action for an intercepted route with dynamic segments, the page would do a full browser refresh. ### Why When constructing rewrites for interception routes, the route params leading up to the interception route are "voided" with a `__NEXT_EMPTY_PARAM__` demarcation. When it comes time to look up the values for these dynamic segments, since the params aren't going to be part of the URL, they get matched via `FlightRouterState` ([ref](https://github.com/vercel/next.js/blob/d67d658ce7396c4b6be1b724be5f45763d5a1803/packages/next/src/server/app-render/app-render.tsx#L153-L201)). The `shouldProvideFlightRouterState` variable only passes it through for RSC requests; however, since the server action will perform the action & return the flight data in a single pass, that means the updated tree from the server action isn't going to receive the `FlightRouterState` when constructing the new tree. This means the old tree will have a `["locale", "en", "d"]` segment, and the new tree from the server action will have `"[locale]"`. When the router detects this kind of segment mismatch, it assumes the user navigated to a new root layout, and triggers an MPA navigation. ### How This unconditionally provides the `FlightRouterState` to `makeGetDynamicParamFromSegment` so that it can properly extract dynamic params for interception routes. We currently enforce interception routes to be dynamic due to this `FlightRouterState` dependency. Fixes #59796 Closes NEXT-2079
@samcx is this fix included in 14.2.0-canary.60? |
I can confirm you can use revalidatePath in server actions submitted using useFormState in the canary.60 release and it no longer redirects to a 404. Yay :) |
i confirm its fixed |
This closed issue has been automatically locked because it had no new activity for 2 weeks. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you. |
Link to the code that reproduces this issue
https://github.com/kahnclusions/nextgram/tree/bug/revalidate-tag-reloads
To Reproduce
http://localhost:3000/en
in a browserCurrent vs. Expected behavior
I expected
Instead
Verify canary release
Provide environment information
Operating System: Platform: darwin Arch: arm64 Version: Darwin Kernel Version 23.0.0: Fri Sep 15 14:43:05 PDT 2023; root:xnu-10002.1.13~1/RELEASE_ARM64_T6020 Binaries: Node: 20.8.1 npm: 10.1.0 Yarn: N/A pnpm: 8.10.5 Relevant Packages: next: 14.0.4 eslint-config-next: N/A react: 18.2.0 react-dom: 18.2.0 typescript: 5.1.3 Next.js Config: output: N/A
Which area(s) are affected? (Select all that apply)
App Router
Additional context
The change that causes the bug is adding the
[locale]
directory and putting everything into the dynamic route. This is a necessary step for doing basic internationalisation. The server action with revalidateTag/Path seems to work fine when added to the base NextGram repo, but after adding the[locale]/
directory and moving everything in there causes it to break.I can reproduce the issue locally in multiple browsers.
The code here never executes when the bug happens: https://github.com/vercel-labs/nextgram/compare/main...kahnclusions:nextgram:bug/revalidate-tag-reloads?expand=1#diff-17ba861615c90b344dff6c88255f992f1cfaae5da0f4d414d9e64d8f518443d8R15-R21
NEXT-2079
The text was updated successfully, but these errors were encountered: