'How do I get smooth scroll and scroll snap to work together in React while also persisting user scroll position on refresh?
I have a custom hook that persists the user's scroll position on page refresh. I also want to implement smooth scrolling for my navigation links (site is a single page, brochure design).
My custom hook works on its own, but adding scroll-behavior: smooth
to the root html
element breaks everything. Similarly, if my window.scrollTo()
call utilizes behavior: 'smooth'
the user is sent to the top of the page on refresh regardless of if I have scroll-behavior: smooth
included or not.
The custom hook is as follows:
const usePersistScrollPosition = (key) => {
const [position, setPosition] = useLocalStorage(key, 0)
useEffect(() => {
window.scrollTo(0, position);
return () => {setPosition(window.scrollY)}
}, [])
return position
}
// Hook taken from https://usehooks.com/useLocalStorage/
const useLocalStorage = (key, initialValue) => {
// State to store our value
// Pass initial state function to useState so logic is only executed once
const [storedValue, setStoredValue] = useState(() => {
try {
// Get from local storage by key
const item = window.localStorage.getItem(key);
// Parse stored json or if none return initialValue
return item ? JSON.parse(item) : initialValue;
} catch (error) {
// If error also return initialValue
console.log(error);
return initialValue;
}
});
// Return a wrapped version of useState's setter function that ...
// ... persists the new value to localStorage.
const setValue = (value) => {
try {
// Allow value to be a function so we have same API as useState
const valueToStore =
value instanceof Function ? value(storedValue) : value;
// Save state
setStoredValue(valueToStore);
// Save to local storage
window.localStorage.setItem(key, JSON.stringify(valueToStore));
} catch (error) {
// A more advanced implementation would handle the error case
console.log(error);
}
};
return [storedValue, setValue];
};
The CSS: (Taken from this CSS tricks article)
html {
scroll-snap-type: proximity;
scroll-snap-points-y: repeat(100vh);
scroll-snap-type: y proximity;
/* scroll-behavior: smooth; */
overflow-y: scroll;
overflow-x: hidden;
max-width: 100vw;
}
What's the best way to utilize smooth scrolling combined with scroll snapping? I also tried using the react-scroll
library but also ran into some difficulties there.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|