如何在useEffect中对scrollY.onChange触发的函数做Debounce/Throttle处理
基于Lodash给滚动监听添加防抖/节流的实现方案
滚动监听场景更推荐用节流(Throttle),可以固定间隔时间触发回调,避免滚动过程中完全不执行逻辑;如果需要滚动停止后才执行逻辑,可以用防抖(Debounce)。具体实现步骤如下:
- 先安装Lodash,推荐按需引入对应方法减少打包体积
- 用
useCallback包裹防抖/节流处理后的update函数,保证函数引用稳定,不会因为组件重渲染失效 - 调整useEffect的依赖项,同时正确注销滚动监听事件、清理未执行的防抖/节流队列
import { useState, useEffect, useCallback } from "react"; import { useViewportScroll } from "framer-motion"; // 按需引入lodash的节流方法,要换防抖就把throttle改成debounce即可 import throttle from "lodash/throttle"; const useScrollScreen = () => { const { scrollY } = useViewportScroll(); const [hidden, setHidden] = useState(false); // 用useCallback包裹保证引用稳定,节流时间可自行调整,这里设为200ms const update = useCallback( throttle(() => { if (scrollY?.current < scrollY?.prev) { console.log("SHOW"); setHidden(false); } else if (scrollY?.current > 100 && scrollY?.current > scrollY?.prev) { setHidden(true); } }, 200), [scrollY] ); useEffect(() => { const unsubscribe = scrollY.onChange(update); // 组件卸载时注销监听同时清空未执行的节流队列 return () => { unsubscribe(); update.cancel(); }; }, [update]); return [hidden, setHidden]; }; export default useScrollScreen;
额外说明:原代码的自定义Hook命名不符合React规范,自定义Hook必须以
use开头,所以将scrollScreen调整为useScrollScreen,避免React语法检查报错。延迟时间可以根据业务需要调整,滚动场景一般设置100~300ms即可平衡流畅度和性能收益。
内容的提问来源于stack exchange,提问作者Martin Seubert
相关产品推荐
相关产品推荐

