#resetting framer-motion's useScroll() upon page change

1 messages · Page 1 of 1 (latest)

pale meteorBOT
#

Hi @marble onyx. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

In Next.js, the scroll position is preserved by default when navigating between pages. This means that if you're at a certain scroll position on one page and navigate to another, the new page will load at the same scroll position. This is likely why your scroll progress bar isn't resetting when you change pages.

There are a few ways you can handle this:

  1. Disable Scroll Restoration: You can disable this behavior by passing scroll: false to router.push() or router.replace(). This will prevent Next.js from preserving the scroll position when navigating to a new route. Here's an example:
import { useRouter } from 'next/navigation'
 
export default function Page() {
 const router = useRouter()
 
 return (
 <button
 type="button"
 onClick={() => router.push('/dashboard', { scroll: false })}
 >
 Dashboard
 </button>
 )
}

(Source: Next.js Documentation (https://nextjs.org/docs/app/api-reference/functions/use-router#disabling-scroll-restoration))

  1. Manual Scroll Restoration: You can manually restore the scroll position to the top of the page when navigating to a new route. Here's an example:
import { useEffect } from "react";

export const ScrollToTop = () => {
  useEffect(() => {
    setTimeout(() => {
      window.scroll(0, 0);
    }, 50);
  }, []);

  return null;
};

(Source: Github Issue (https://github.com/vercel/next.js/issues/28778))

  1. Persistent Scroll Position: If you want to preserve the scroll position for some pages but not others, you can use a more complex solution that involves storing the scroll position in localStorage and restoring it when necessary. Here's an example:
export const usePersistentScroll = () => {
  const router = useRouter()
  const searchParams = useSearchParams()
  const pathname = usePathname()
#

useEffect(() => {
const persistentScroll = localStorage.getItem('persistentScroll')
if (persistentScroll === null) return

window.scrollTo({ top: Number(persistentScroll) })

if (Number(persistentScroll) === window.scrollY) localStorage.removeItem('persistentScroll')

}, [searchParams])

const saveScrollPosition = useCallback(() => {
localStorage.setItem('persistentScroll', window.scrollY.toString())
}, [])

const setSearchParam = useCallback(
(key: string, value: string) => {
const currentParams = searchParams?.toString()
const params = new URLSearchParams(currentParams)

  params.set(key, value)

  if (currentParams === params.toString()) return

  saveScrollPosition()
  router.push(`${pathname}?${params.toString()}`)
},
[searchParams, pathname, router, saveScrollPosition],

)

return { setSearchParam, saveScrollPosition }
}

(Source: **Github Issue** (<https://github.com/vercel/next.js/issues/49087>))

Please note that these solutions might not work perfectly with Framer Motion's `useScroll()` hook, as it might have its own way of handling scroll events. You might need to adapt these solutions to work with Framer Motion.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------