Scroll Restoration
Paling rapi dari beberapa implementasi scroll restoration yang pernah saya terapkan. Syaratnya: context + refFergus Hagaswara
•
1/15/2023
Artikel singkat ini akan membahas bagaimana mengimplementasikan scroll restoration pada project React dan NextJS.
Context Provider
Hal pertama yang harus dilakukan adalah membuat provider untuk scroll restoration. Saya akan buat di src/providers/ScrollProvider
/*
src/providers/ScrollProvider/ScroProvider.tsx
*/
import {createContext, MutableRefObject, ReactNode, useContext, useEffect, useRef} from 'react'
type AppContextType = {
scrollRef: MutableRefObject<{scrollPos: number}>
}
const AppContext = createContext<AppContextType | undefined>(undefined)
const ScrollProvider = ({children}: {children: ReactNode}) => {
const scrollRef = useRef({
scrollPos: 0
})
return <AppContext.Provider value={{scrollRef}}>{children}</AppContext.Provider>
}
const useProvider = () => {
const context = useContext(AppContext)
if (context === undefined) {
throw new Error('You are using the hook outside of the scroll provider')
}
useEffect(() => {
window.scrollTo(0, context.scrollRef.current.scrollPos)
const handleScrollPos = () => {
context.scrollRef.current.scrollPos = window.scrollY
}
window.addEventListener('scroll', handleScrollPos)
return () => {
window.removeEventListener('scroll', handleScrollPos)
}
}, [])
return context
}
export {ScrollProvider, useProvider}
kemudian entry point untuk provider tadi
/*
src/providers/ScrollProvider/index.ts
*/
import {ScrollProvider, useProvider} from './ScrollProvider'
export default ScrollProvider
export {useProvider as useScrollRestoration}
Pemakaian
Gunakan <ScrollProvider>
di entry point project anda sebelum komponen lainnya di render.
untuk NextJS di pages/_app.tsx
const MyApp = ({Component, pageProps}: AppProps) => {
return (
<ScrollProvider>
<Component {...pageProps} />
</ScrollProvider>
)
}
untuk CRA di src/index.tsx
root.render(
<React.StrictMode>
<ScrollProvider>
<App />
</ScrollProvider>
</React.StrictMode>
)
dan import useScrollRestoration
di komponen yang membutuhkan scroll restoration
import React from 'react'
import {useScrollRestoration} from 'src/providers/ScrollProvider'
const PageWithLongContent = () => {
useScrollRestoration()
return (
//long scrollable content
)
}
Untuk NextJS jangan lupa menambahkan props scroll={false}
di setiap <Link>
yang menuju halaman yang menggunakan useScrollRestoration()
. Tujuannya agar router NextJS tidak menjalankan default behaviour nya yaitu otomatis scroll ke paling atas halaman saat melaukan navigasi.
Kesimpulan
Menurut saya implementasi scroll restoration ini adalah yang paling efisien dan rapi dari beberapa implementasi yang pernah saya terapkan. Tidak membutuhkan package tambahan, tidak menimbulkan masalah performa karena menggunakan ref
untuk menyimpan posisi scroll terakhir, dan tidak menambahkan banyak kode-kode boilerplate pada pemakaiannya seperti yang sudah saya contohkan di atas.
Yang perlu diperhatikan adalah kemungkinan besar scroll restoration ini kurang memadai untuk menangani routing yang kompleks. Sebagai contoh perlu ditambahkan fungsionalitas untuk melakukan mapping posisi scroll untuk masing-masing halaman, sehingga posisi scroll terakhir yang akan di restore lebih presisi dan tidak saling tercampur.