Horizontal Scrolling on React Component Using Vertical Mouse Wheel

2 min read 06-10-2024
Horizontal Scrolling on React Component Using Vertical Mouse Wheel


Scroll Your React Component Horizontally with the Vertical Mouse Wheel

Imagine a React component filled with a long list of items, and you want users to navigate through it horizontally using their familiar vertical mouse wheel. This intuitive approach can greatly enhance the user experience, making navigation smoother and more natural.

The Challenge:

React's default behavior doesn't allow for horizontal scrolling using the vertical mouse wheel. We need to find a way to intercept the wheel event, extract the scroll direction, and then apply it to the horizontal scroll position of our component.

Scenario:

Let's say we have a React component called ScrollableList displaying a list of images:

import React, { useState, useRef, useEffect } from 'react';

function ScrollableList({ images }) {
  const [scrollLeft, setScrollLeft] = useState(0);
  const scrollableRef = useRef(null);

  const handleScroll = (e) => {
    // ...  We need to capture the wheel event here and update scrollLeft 
  };

  useEffect(() => {
    if (scrollableRef.current) {
      scrollableRef.current.addEventListener('wheel', handleScroll);
    }
    return () => {
      if (scrollableRef.current) {
        scrollableRef.current.removeEventListener('wheel', handleScroll);
      }
    };
  }, []);

  return (
    <div ref={scrollableRef} style={{ overflowX: 'auto' }}>
      <div style={{ display: 'flex', gap: '20px' }}>
        {images.map((image, index) => (
          <img key={index} src={image} alt={`Image ${index + 1}`} />
        ))}
      </div>
    </div>
  );
}

Solution:

We can achieve this by using the wheel event listener and extracting the deltaY value, which represents the vertical scroll amount. We can then adjust the horizontal scroll position (scrollLeft) based on the deltaY value.

import React, { useState, useRef, useEffect } from 'react';

function ScrollableList({ images }) {
  const [scrollLeft, setScrollLeft] = useState(0);
  const scrollableRef = useRef(null);

  const handleScroll = (e) => {
    const deltaY = e.deltaY; // Get the vertical scroll amount
    setScrollLeft(scrollLeft + deltaY); // Update scrollLeft based on deltaY
  };

  useEffect(() => {
    if (scrollableRef.current) {
      scrollableRef.current.addEventListener('wheel', handleScroll);
    }
    return () => {
      if (scrollableRef.current) {
        scrollableRef.current.removeEventListener('wheel', handleScroll);
      }
    };
  }, []);

  return (
    <div ref={scrollableRef} style={{ overflowX: 'auto' }}>
      <div style={{ display: 'flex', gap: '20px' }}>
        {images.map((image, index) => (
          <img key={index} src={image} alt={`Image ${index + 1}`} />
        ))}
      </div>
    </div>
  );
}

export default ScrollableList;

Explanation:

  • We use a useRef hook to keep a reference to the scrollable container (scrollableRef).
  • The handleScroll function captures the wheel event and extracts the deltaY value.
  • We update the scrollLeft state with the previous value plus the deltaY. This allows us to scroll horizontally based on the vertical wheel movement.
  • The useEffect hook ensures that the wheel event listener is added and removed appropriately when the component mounts and unmounts.

Enhancements:

  • Scroll Speed Adjustment: We can customize the scroll speed by multiplying the deltaY value with a factor. This provides greater control over the responsiveness of the scroll behavior.
  • Preventing Default Behavior: For certain scenarios, it might be desirable to prevent the default scroll behavior of the page. This can be achieved by calling e.preventDefault() within the handleScroll function.
  • Smooth Scrolling: We can create a smoother scrolling experience by using requestAnimationFrame or other animation libraries to handle the scroll updates gradually.

Conclusion:

By manipulating the wheel event and updating the scrollLeft state, we can effortlessly implement horizontal scrolling using the vertical mouse wheel in our React components. This approach provides a more natural and intuitive navigation experience for users.

Remember to adapt this solution to your specific needs, considering scroll speed, default behavior prevention, and smooth scrolling enhancements.