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

React Hook useSlideScroll在点击回调中调用触发规则报错,求助排查

问题原因与解决方案

核心问题

  1. 错误的Hook命名与定义:你写的useSlideScroll根本不是符合React规范的自定义Hook——它没有调用任何React内置Hook(比如useState、useEffect),本质就是一个普通工具函数。但你给它加了use前缀,导致ESLint的react-hooks/rules-of-hooks规则将其判定为Hook,触发检查。
  2. 违反Hook调用规则:即便它是真的Hook,也绝对不能在onClick这类事件回调里调用。React要求Hook必须在函数组件或自定义Hook的顶层作用域调用,不能嵌套在循环、条件判断、事件回调中,否则会破坏Hook的状态维护逻辑。

修复步骤

1. 将"伪Hook"改为普通工具函数

去掉use前缀,改成普通函数,还可以增加空值判断避免报错:

// hooks/slideScroll.js
export const slideScroll = (element, speed, distance, step) => {
  if (!element) return; // 防止DOM元素未挂载的情况
  let scrollAmount = 0;
  const slideTimer = setInterval(() => {
    element.scrollLeft += step;
    scrollAmount += Math.abs(step);
    if (scrollAmount >= distance) {
      clearInterval(slideTimer);
    }
  }, speed);
  return slideTimer; // 返回定时器ID,方便后续清理
};

2. 在组件中正确调用工具函数

增加定时器的清理逻辑,避免快速点击导致多个定时器同时运行,以及组件卸载时的内存泄漏:

import { useRef, useEffect } from 'react';
import { slideScroll } from '../hooks/slideScroll';
import Image from 'next/image'; // 假设你用的是Next.js的Image组件

const YourComponent = () => {
  const scrollRef = useRef(null);
  const timerRef = useRef(null); // 保存定时器ID,用于清理

  const handlePrevClick = () => {
    // 先清理之前的定时器,避免冲突
    if (timerRef.current) {
      clearInterval(timerRef.current);
    }
    // 调用工具函数
    timerRef.current = slideScroll(scrollRef.current, 25, 100, -10);
  };

  // 组件卸载时清理定时器
  useEffect(() => {
    return () => {
      if (timerRef.current) {
        clearInterval(timerRef.current);
      }
    };
  }, []);

  return (
    <div ref={scrollRef} className="overflow-x-auto">
      {/* 你的滚动内容 */}
      <Image
        src={'/images/prevArrow.svg'}
        alt="arrow left"
        height="10"
        width="10"
        className="cursor-pointer h-[10px] w-[10px]"
        onClick={handlePrevClick}
      />
    </div>
  );
};

export default YourComponent;

补充说明

  • React自定义Hook的核心是复用状态逻辑,必须依赖React内置Hook实现,且命名必须以use开头。如果只是纯逻辑的工具函数,不需要用Hook的方式定义。
  • 事件回调是用户交互时才执行的代码,而Hook需要在组件每次渲染时按固定顺序调用,所以绝对不能在回调里调用Hook。

内容的提问来源于stack exchange,提问作者Valentino Fabris Valenti

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 03:05:28