【问题标题】:Wheel event triggers many times react车轮事件触发多次反应
【发布时间】:2019-12-02 10:16:26
【问题描述】:

我正在尝试实现整页滚动。我的问题是车轮事件经常触发两次。 我在 vanilla js 上实现了它,并且效果很好。

const [ index, setIndex ] = useState(0);
const sectionWrapper = useRef();
const animationBreak = 750;
const maxIndex = 2;
let lastTime = 0;

useEffect(
    () => {
        const handleWheel = e => {
            const sections = sectionWrapper.current.children;
            const wheelDirection = e.wheelDelta;
            const currentTime = new Date().getTime();
            const isAnimationEnable = currentTime - lastTime > animationBreak;

            if (!isAnimationEnable) return;

            if (wheelDirection < 0 && index < maxIndex) {
                setIndex(index + 1);
            }

            if (wheelDirection > 0 && index > 0) {
                setIndex(index - 1);
            }

            sections[index].scrollIntoView({ behavior: 'smooth' });
            lastTime = currentTime;
        };

        window.addEventListener('wheel', handleWheel);

        return () => window.removeEventListener('wheel', handleWheel);
    },
    [ index ]
);

我尝试使用 lodash 的方法,如油门或去抖动。不适合我。

【问题讨论】:

    标签: javascript reactjs dom-events react-hooks mousewheel


    【解决方案1】:

    您不需要在每次索引更改时删除/重新分配事件处理程序,事件处理代码永远不会更改,您只需要访问最近的index 状态。您可以通过在 setX 函数上使用回调来做到这一点,例如

    useEffect(() => {
      const handleWheel = e => {
        const sections = sectionWrapper.current.children;
        const wheelDirection = e.wheelDelta;
        const currentTime = new Date().getTime();
        const isAnimationEnable = currentTime - lastTime > animationBreak;
    
        if (!isAnimationEnable) return;
    
        let index;
        setIndex(i => index = i); // read most recent index
        // use a temp var to get the new state value for scrolling later
        let newIndex;
        if (wheelDirection < 0 && index < maxIndex) {
          setIndex(i => (newIndex = ++i)); // increment the current index by 1
        }
    
        if (wheelDirection > 0 && index > 0) {
          setIndex(i => (newIndex = --i)); // decrement the current index by 1
        }
    
        sections[newIndex].scrollIntoView({ behavior: 'smooth' });
        lastTime = currentTime;
      };
    
      window.addEventListener('wheel', handleWheel);
    
      return () => window.removeEventListener('wheel', handleWheel);
    }, []); // we no longer need any dependences here
    

    【讨论】:

    • 我认为使用变量访问索引状态很棘手。这是为什么?为什么我们不能直接访问索引状态?
    • 现在我遇到了条件index &lt; maxIndexindex &gt; 0 的问题。如果索引是可变的,它总是未定义的。如果索引是状态,则它始终为 0。
    • @nukuutos 哦,抱歉,我的本地 var 将与 state var 的名称发生冲突 - 让我更新一下
    • 我上次了解你。它工作不正确。我想处理 var。再说一遍:“使用变量访问索引状态很棘手。为什么会这样?为什么我们不能直接访问索引状态?”
    • @nukuutos 我明白为什么它目前不能正常工作,handleWheel 处理程序在useEffect 内创建一次,然后再不会重新创建,这意味着状态逻辑永远不会改变。让我更新修复
    【解决方案2】:

    useRef 以更简洁的方式解决了这个问题。

        const [ index, setIndex ] = useState(0);
        // using useRef to ref to index
        const indexRef = useRef();
        indexRef.current = index;
    
        useEffect(() => {
            const handleWheel = e => {
                const sections = sectionWrapper.current.children;
                const wheelDirection = e.wheelDelta;
                const currentTime = new Date().getTime();
                const isAnimationEnable = currentTime - lastTime > animationBreak;
    
                if (!isAnimationEnable) return;
    
                if (wheelDirection < 0 && indexRef.current < maxIndex) {
                    setIndex(() => indexRef.current + 1);
                    sections[indexRef.current].scrollIntoView({ behavior: 'smooth' });
                }
    
                if (wheelDirection > 0 && indexRef.current > 0) {
                    setIndex(() => indexRef.current - 1); 
                    sections[indexRef.current].scrollIntoView({ behavior: 'smooth' });
                }
    
                lastTime = currentTime;
            };
    
            window.addEventListener('wheel', handleWheel);
    
            return () => window.removeEventListener('wheel', handleWheel);
        }, []); 
    

    【讨论】:

      猜你喜欢
      • 2022-08-17
      • 2020-06-19
      • 2016-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多