next.js: [Examples] Modal dynamic route doesn't keep scroll position
Bug report
The example from https://github.com/vercel/next.js/tree/canary/examples/with-route-as-modal doesn’t keep scroll position when modal is opened using the dynamic routing method.
Describe the bug
I’m not sure if the dynamic routing method is supposed to work like the QueryString routing where it keeps the scrolling position of the main page. I’m not able to use the QueryString method due to getStaticProps()
not working as a component correctly (can’t use mongodb node driver, it errors saying dns could not be found)
The scrolling position is saved when using the QueryString method after you close the modal. But for the dynamic routing method, it unloads the main page and only shows the modal (as seen in the gif below). When the modal is exited, the main page is reloaded again and the scroll position from the previous context is lost.
To Reproduce
yarn create next-app --example with-route-as-modal with-route-as-modal-app
cd with-route-as-modal-app
yarn dev
- Go to
localhost:3000
in Safari - Click on one of the numbers under “With Dynamic Routing, and reloads will keep the modal”
- Exit out of the modal by clicking on the outer area of the screen.
Expected behavior
When exiting out of the modal, it should keep the scroll position of the main page.
Screenshots
System information
- OS: macOS 11.0 Beta (20A5364e)
- Browser: Safari 14.0 (16610.2.2.4)
- Version of Next.js: v9.5.3
- Version of Node.js: v12.18.3
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 1
- Comments: 22 (12 by maintainers)
@kyleawayan I threw up a repo where I’ve used a couple concepts that break with the original example; namely this is using
layouts
Seems to be keeping the scroll as desired via
scroll={false}
on<Link />
when the page components via layouts are essentially all the same.This was my hunch on how to achieve what you’re looking for and I tried to be descriptive in the
Headings
to illustrate the differences in functionality for query string vs. dynamic routing.Give it a look and let me know of any questions 👍 https://github.com/jmfury/nextjs-route-as-modal-plus-scroll
@kyleawayan Great to hear it’s working! Feel free to tag me on any code you can share outside this thread as needed. Happy to assist if any of the concepts are giving you any trouble in your implementation!
What a fun day! Next.js actually should’ve properly sorted me out with using the router methods / Link with
scroll=false
; however, the real problem was that the scrolling container was actually a virtualized list attached to an element that wasn’t window… I adapted the gist’s hook to work with a custom element and we’re flying now.Right, we’re following persistent layouts and the 2 pages in question use the same layout; however, unlike modals as routes, we’re rendering 2 entirely different pages. The only code each page file shares is the layout.
I guess I could embed routing logic within the layout and match up with your example, but I think I may use the gist Kyle provided instead. Seems a little more obvious/declarative.
@jmfury Nevermind, I understood the flow wrong. I tried changing the
getStaticProps()
in[articleId].js
toand it reflected on all the pages!
@kyleawayan Glad to help! I think the key here is eliminating the need for
next
(react
on the client?) to unmount your page component which was the case in the original example. The pages were very different components in dynamic routing navigation.Reloads are essentially a new server-render so I don’t think keeping the scroll is typically desired anyway. It is potentially doable with
next/router
events… not positive, but I found this along the way as food for thought 🔗Hi everyone! Just wanted to leave an update here: I got it working with my website! Ends up I really couldn’t get the dynamic routing working since my page was re-rendering every time the modal closed… But I found a solution! Instead of using
getStaticProps()
, I used SWR to fetch data on the client-side. I made an API route that gets the same data thatgetStaticProps()
does, then implemented SWR into a component, and used the QueryString method given in @jmfury’s example. So now I basically have a modal component for my “sub-gallery” for the QueryString modal, and a dynamically routed page with basically the same content as the modal component, the only difference is that it’s usinggetStaticProps()
.It works perfectly! You can check it out on my website.
Thank you to @jmfury for your example repo and everyone that helped!
@jmfury Thank you! I have one problem, I’m going to try to explain what I have right now… but first let me explain how my website works.
If you go to my website, there is an initial gallery that the user sees. They then can click any photo, and then it will go to like a “sub-gallery” you could say.
My home page gallery (like your Grid component in your example) uses
getStaticProps()
to get photos for the home page. I then pass that on to myHomeGallery
layout which it is then rendered.But when I go to a “sub-gallery,” the layout can’t load the initial
getStaticProps()
which was passed on from the home page gallery since it’s not on that page (index.js
) anymore.I’m not sure if your example reloads the whole page, or it’s because I’m using
getStaticProps()
, everything is getting messed up. FYI, I’m usingrouter.push
as I can’t really map<Link>
s to each photo inreact-photo-gallery
. I even tried making a dummy link withscroll={false}
just to try it but it’s still resulting in the same issue.Do you recommend any other ways to circumvent this?
@jmfury Wow thank you so much for this! I cloned your repo and it works on my end! Now I just need to figure out how to incorporate it to my website. Although reloading will lose the scroll position, it’s good enough as people looking through my gallery won’t really need to reload. But you got the exact thing I was looking for!