You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中使用useRef绑定元素点击时无法触发滚动的问题

React 横向滚动功能失效修复

问题表现

点击左右滚动控制按钮时,预期触发onClickScroll方法修改绑定ref的DOM元素scrollLeft属性实现横向滚动,实际无任何滚动效果。
相关原代码如下:
滚动逻辑代码:

const scrollRef = useRef<HTMLDivElement | null>(null);
const onClickScroll = (scrollOffset: number) => {
  scrollRef!.current!.scrollLeft += scrollOffset;
};

控制按钮代码:

<span className="flex">
 <ChevronLeftIcon className="h-5 w-5 text-white cursor-pointer" onClick={()=> onClickScroll(-20)}/>
 <ChevronRightIcon className="h-5 w-5 text-white cursor-pointer" onClick={() => onClickScroll(20)}/>
</span>

可滚动容器代码:

<div className="flex mt-5 w-[80rem] overflow-scroll overflow-y-clip scrollbar-hide" ref={scrollRef}>Somecode</div>

核心根因

可滚动容器设置了flex布局,其直接子元素默认flex-shrink属性值为1,会自动收缩宽度适配容器尺寸,哪怕子元素总宽度超过容器的80rem,也会被压缩到容器宽度范围内,不会产生横向溢出。没有可滚动的溢出空间时,修改scrollLeft属性不会产生任何滚动效果。
除此之外还有三个潜在隐患会导致滚动失效:

  • 代码使用TS非空断言强制跳过ref空值校验,组件挂载前触发方法会直接报错
  • 直接给自定义图标组件绑定onClick事件,部分组件未做事件透传时,点击根本不会触发回调
  • 使用overflow-y-clip属性在部分浏览器版本存在兼容性问题,会干扰滚动行为

修复步骤

  1. 给可滚动容器的所有直接子元素添加shrink-0类(对应flex-shrink: 0),禁止子元素自动收缩,确保内容总宽度超出容器时能产生横向溢出。同时将容器的overflow样式替换为兼容性更好的写法:
<div className="flex mt-5 w-[80rem] overflow-x-auto overflow-y-hidden scrollbar-hide" ref={scrollRef}>
  {/* 所有直接子元素都要加shrink-0,示例如下 */}
  <div className="shrink-0 w-[32rem]">内容块1</div>
  <div className="shrink-0 w-[32rem]">内容块2</div>
  <div className="shrink-0 w-[32rem]">内容块3</div>
</div>
  1. 给滚动逻辑加空值兜底,去掉不安全的非空断言:
const scrollRef = useRef<HTMLDivElement | null>(null);
const onClickScroll = (scrollOffset: number) => {
  if (!scrollRef.current) return;
  scrollRef.current.scrollLeft += scrollOffset;
};
  1. 给图标外层套原生button元素绑定点击事件,给图标加pointer-events-none避免事件触发异常,同时提升可访问性:
<span className="flex">
  <button
    className="p-1 cursor-pointer bg-transparent border-none"
    onClick={() => onClickScroll(-20)}
    aria-label="向左滚动"
  >
    <ChevronLeftIcon className="h-5 w-5 text-white pointer-events-none"/>
  </button>
  <button
    className="p-1 cursor-pointer bg-transparent border-none"
    onClick={() => onClickScroll(20)}
    aria-label="向右滚动"
  >
    <ChevronRightIcon className="h-5 w-5 text-white pointer-events-none"/>
  </button>
</span>

验证方法

修改完成后打开浏览器开发者工具,选中绑定ref的滚动容器DOM,查看属性面板:如果scrollWidth数值大于clientWidth数值,说明容器已经产生有效横向溢出,此时点击按钮即可正常触发滚动。

内容的提问来源于stack exchange,提问作者Sai Krishnadas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 21:33:44