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

如何在useEffect外部访问其内部定义的IScroll实例实现按钮控制滚动?

解决方案

你可以通过useRef存储IScroll实例解决作用域访问问题,这是React中存储不需要触发重渲染的可变值的标准方案,你之前用state报错是因为state更新为异步逻辑,且state变更会触发额外重渲染,不适合存储第三方类实例。

修改后的完整代码如下:

function Arrangement() {
  const ref = useRef(null);
  // 新增ref存储iscroll实例
  const iscrollRef = useRef(null);

  const [prevButton, setPrevButton] = useState(false);
  const [nextButton, setNextButton] = useState(true);

  useEffect(() => {
    const iscroll = new IScroll(ref.current, {
      keyBindings: true,
      scrollX: true,
      mouseWheel: true,
      click: true
    });
    // 将实例挂载到ref上
    iscrollRef.current = iscroll;

    iscroll.on("scrollEnd", () => {
      if (iscroll.x === 0) {
        setPrevButton(false);
      } else {
        setPrevButton(true);
      }

      if (iscroll.x === iscroll.maxScrollX) {
        setNextButton(false);
      } else  {
        setNextButton(true);
      }
    });

    return () => {
      iscroll.destroy();
      // 卸载时清空ref避免内存泄漏
      iscrollRef.current = null;
    }
  }, []);

  const onPrevButtonHandler = () => {
    // 先判断实例是否存在,避免初始化未完成时报错
    if (!iscrollRef.current) return;
    iscrollRef.current.scrollBy(220, 0, 600);
  }

  const onNextButtonHandler = () => {
    if (!iscrollRef.current) return;
    iscrollRef.current.scrollBy(-220, 0, 600);
  }

  return (
    <div className={classes.Container}>
      <button className={clsx(classes.Button, classes.ButtonLeft, {
        [classes.Button__active]: prevButton
      })} onClick={onPrevButtonHandler} type="button" aria-label="Prev button">
        <ChevronLeft />
      </button>
      <div className={classes.Wrapper} ref={ref}>
        <ul>
          <li></li>
        </ul>
      </div>
      <button className={clsx(classes.Button, classes.ButtonRight, {
        [classes.Button__active]: nextButton
      })} onClick={onNextButtonHandler} type="button" aria-label="Next button">
        <ChevronRight />
      </button>
    </div>
  );
}

export default Arrangement;

核心说明

  • useRef的current属性读写都是同步操作,不会触发组件重渲染,完美适配存储第三方库实例的场景
  • 点击事件中新增的非空判断可以避免IScroll未初始化完成时用户点击按钮抛出异常
  • 清理函数中新增的清空ref操作可以避免组件卸载后出现野指针导致的内存泄漏问题

内容的提问来源于stack exchange,提问作者Emil Jamel Mahmuda

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 05:12:03