47ng / nuqs

Type-safe search params state manager for Next.js - Like React.useState, but stored in the URL query string.

Home Page:https://nuqs.47ng.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Scroll to top of the page not working in mobile devices

frontendparham opened this issue · comments

Hi, I have this code:

const [searchQueryUrl, setSearchQueryUrl] = useQueryState("search", {
    defaultValue: "",
    scroll: true,
    history: "push",
  });

The scroll to top of the page on query change works fine on desktops but not working in mobile devices.

Can you reproduce the same behaviour with calls to the Next.js router on mobile (which OS/Browser) ?

import { useRouter } from 'next/navigation'

function MyComponent() {
  const router = useRouter()
  const onClick = () => router.replace(`?test=${Math.random()}`, { scroll: true })
  return <button onClick={onClick}>Test</button>
}

Can you reproduce the same behaviour with calls to the Next.js router on mobile (which OS/Browser) ?

import { useRouter } from 'next/navigation'

function MyComponent() {
  const router = useRouter()
  const onClick = () => router.replace(`?test=${Math.random()}`, { scroll: true })
  return <button onClick={onClick}>Test</button>
}

Yes with this code you have wrote the browser go to top of the page. and I'm testing on android / chrome

I have added a reproduction example here: https://next-usequerystate-preview.vercel.app/demos/repro-376 (source)

However it works fine on Chrome 118 on Android 10. Let me know if there are other things that may be relevant to reproduce your issue.

The impacting code line that deals with scroll isn't actually related to the Next router, since your setup uses shallow mode.

What happens if you call window.scroll(0,0) ? This should scroll to the top of the page.

I have added a reproduction example here: https://next-usequerystate-preview.vercel.app/demos/repro-376 (source)

However it works fine on Chrome 118 on Android 10. Let me know if there are other things that may be relevant to reproduce your issue.

The impacting code line that deals with scroll isn't actually related to the Next router, since your setup uses shallow mode.

What happens if you call window.scroll(0,0) ? This should scroll to the top of the page.

Yes, it's possible that the issue is caused by the position: sticky on the header. I placed the search bar inside the sticky header, and I expect that when search query changes the page scroll to the top, but unfortunately, it doesn't happen, and I'm not sure how to resolve it.
Also I put window.scroll(0, 0); inside my click handler before updating the query, but this also not worked.

Anyway, I find your hook very useful. Thank you.

Ah that makes more sense.

If you find a way to reference your main view, you could call scrollTop on it after a query update.

It seems that the smooth scrolling is not working while you have a sticky element on top of the page so I put this code after query update and it fixes my issue. now after query update the page scroll to top instantly.

window.scrollTo({
        top: 0,
        behavior: "instant",
      });

What would you think of an API like this?

useQueryState('query', parseAsString
  .withOptions({
    scroll: {
      // top defaults to 0 if scroll is an object
      behavior: 'instant' // but we can configure other properties
    }
    history: 'push'
  })
  .withDefault('')

One issue with this approach is for non-shallow updates, which use the Next.js router and are limited to what it supports (only a boolean at this time). There may be some race conditions with the server response changing the content of the page and scrolling, not sure what the current behaviour is at the moment.

Yes, this could be very helpful for those facing similar issues. .However, as you mentioned, there are several factors to consider, and it might not address all scenarios.

Closing this issue as not strictly lib-related, and there is a workaround:

setSearchQueryUrl('example.com').then(() => window.scrollTo({ top: 0, behavior: 'instant' }))