前言

本节我们实现一个简洁的自定义 React Hook,它可以检测用户的滚动方向:

import * as React from 'react';

const THRESHOLD = 0;

const useScrollDirection = () => {
  const [scrollDirection, setScrollDirection] = React.useState('up');

  const blocking = React.useRef(false);
  const prevScrollY = React.useRef(0);

  React.useEffect(() => {
    prevScrollY.current = window.pageYOffset;

    const updateScrollDirection = () => {
      const scrollY = window.pageYOffset;

      if (Math.abs(scrollY - prevScrollY.current) >= THRESHOLD) {
        const newScrollDirection =
          scrollY > prevScrollY.current ? 'down' : 'up';

        setScrollDirection(newScrollDirection);

        prevScrollY.current = scrollY > 0 ? scrollY : 0;
      }

      blocking.current = false;
    };

    const onScroll = () => {
      if (!blocking.current) {
        blocking.current = true;
        window.requestAnimationFrame(updateScrollDirection);
      }
    };

    window.addEventListener('scroll', onScroll);

    return () => window.removeEventListener('scroll', onScroll);
  }, [scrollDirection]);

  return scrollDirection;
};

export { useScrollDirection };

在一个函数组件中,自定义的 React Hook可以这样使用:

import * as React from 'react';

import { useScrollDirection } from './useScrollDirection';

const App = () => {
  const scrollDirection = useScrollDirection(ref);
  console.log('up');

  return (...);
};

最后,可能有很多方法可以改进这个自定义Hook(例如,检查水平而不是垂直滚动方向)。