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

React路由切换时useRef报Cannot read property 'style' of null错误如何解决

问题根因
  • useRef未指定类型与初始值,默认初始值为undefined,TypeScript无法确定其是否存在,因此抛出2532类型错误
  • 平滑滚动的requestAnimationFrame循环未设置清理逻辑,路由切换组件卸载后,循环仍在执行,此时scrollingContainerRef.current已经被销毁为null,访问style属性就会抛出空指针错误
  • 所有用到scrollingContainerRef.current的逻辑未做存在性校验,ref未完成挂载时调用就会报错
  • 滚动状态data定义在组件函数体内,每次组件重渲染都会被重置为初始值,会导致滚动逻辑异常,属于隐藏bug
修复步骤
  1. 给useRef指定HTMLDivElement类型,初始值设为null
  2. 用useRef存储滚动状态data与requestAnimationFrame的id,避免重渲染重置
  3. 所有访问scrollingContainerRef.current的逻辑前置判空
  4. 在useEffect的清理函数中取消requestAnimationFrame循环,组件卸载时停止滚动逻辑
修复后完整代码
const Scroll: React.FC = ({ children }) => {
  const windowSize = useWindowSize();
  // 给ref指定类型和初始值
  const scrollingContainerRef = useRef<HTMLDivElement>(null);
  // 用useRef存储滚动状态和raf id,避免重渲染被重置
  const dataRef = useRef({
    ease: 0.1,
    current: 0,
    previous: 0,
    rounded: 0,
  });
  const rafIdRef = useRef<number>();

  const setBodyHeight = () => {
    // 先判断ref存在再执行逻辑
    if (isBrowser && scrollingContainerRef.current) {
      document.body.style.height = `${
        scrollingContainerRef.current.getBoundingClientRect().height
      }px`;
    }
  };

  useEffect(() => {
    setBodyHeight();
  }, [windowSize.height]);

  const smoothScrollingHandler = () => {
    // 先判断ref存在再执行滚动逻辑
    if (!scrollingContainerRef.current) return;
    const data = dataRef.current;
    data.current = isBrowser ? window.scrollY : 0;
    data.previous += (data.current - data.previous) * data.ease;
    data.rounded = Math.round(data.previous * 100) / 103;
    scrollingContainerRef.current.style.transform = `translateY(-${data.previous}px)`;

    rafIdRef.current = requestAnimationFrame(() => smoothScrollingHandler());
  };

  useEffect(() => {
    rafIdRef.current = requestAnimationFrame(() => smoothScrollingHandler());
    // 组件卸载时清理raf循环
    return () => {
      if (rafIdRef.current) {
        cancelAnimationFrame(rafIdRef.current);
      }
    };
  }, []);

  return (
    <Wrapper>
      <div ref={scrollingContainerRef}>{children}</div>
    </Wrapper>
  );
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.19 08:27:08