'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