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

页面初始渲染后平滑滚动定位异常的修复方法咨询

修复react-scroll Link组件首次平滑滚动定位偏移问题

页面加载/更新后首次点击react-scroll的Link组件,平滑滚动位置偏下;手动滚动或二次点击后恢复正常;关闭smooth属性则首次定位正常。


方案1:动态计算偏移量(解决布局未稳定导致的固定offset误差)

首次加载时页面布局可能未完全稳定(比如导航栏高度由异步内容决定),固定的offset=-130会出现偏差。改为动态获取目标元素或导航栏的实际高度来计算偏移:

"use client";

import React, { useState, useEffect } from "react";
import { Link } from "react-scroll";

interface ButtonNavigationProps {
  navigateTo: string;
  children: React.ReactNode;
}

const ButtonNavigation: React.FC<ButtonNavigationProps> = ({
  navigateTo,
  children,
}) => {
  const [offset, setOffset] = useState(-130);

  useEffect(() => {
    // 假设导航栏的id是"navbar",动态获取其高度
    const navbar = document.getElementById("navbar");
    if (navbar) {
      setOffset(-navbar.offsetHeight);
    }
    // 监听窗口 resize,更新偏移量
    const handleResize = () => {
      if (navbar) setOffset(-navbar.offsetHeight);
    };
    window.addEventListener("resize", handleResize);
    return () => window.removeEventListener("resize", handleResize);
  }, []);

  return (
    <Link
      smooth={true}
      spy={true}
      isDynamic={true}
      to={navigateTo}
      offset={offset}
      duration={650}
      className="flex items-center gap-x-2 px-8 py-3"
    >
      {children}
      <svg
        xmlns="http://www.w3.org/2000/svg"
        height="24"
        viewBox="0 -960 960 960"
        width="24"
        fill="currentColor"
      >
        <path d="m560-240-56-58 142-142H160v-80h486L504-662l56-58 240 240-240 240Z" />
      </svg>
    </Link>
  );
};

export default ButtonNavigation;

方案2:禁用isDynamic并手动刷新滚动计算

isDynamic属性可能在首次加载时干扰元素位置检测,关闭后配合组件挂载时刷新scroll实例:

"use client";

import React, { useEffect } from "react";
import { Link, scroller } from "react-scroll";

interface ButtonNavigationProps {
  navigateTo: string;
  children: React.ReactNode;
}

const ButtonNavigation: React.FC<ButtonNavigationProps> = ({
  navigateTo,
  children,
}) => {
  useEffect(() => {
    // 组件挂载后刷新scroll的位置计算
    scroller.refresh();
  }, []);

  return (
    <Link
      smooth={true}
      spy={true}
      isDynamic={false} // 禁用动态检测
      to={navigateTo}
      offset={-130}
      duration={650}
      className="flex items-center gap-x-2 px-8 py-3"
    >
      {children}
      <svg
        xmlns="http://www.w3.org/2000/svg"
        height="24"
        viewBox="0 -960 960 960"
        width="24"
        fill="currentColor"
      >
        <path d="m560-240-56-58 142-142H160v-80h486L504-662l56-58 240 240-240 240Z" />
      </svg>
    </Link>
  );
};

export default ButtonNavigation;

方案3:替换为原生平滑滚动(绕过react-scroll的bug)

如果以上方案无效,直接使用浏览器原生的scrollIntoView实现平滑滚动,避免依赖react-scroll的内部逻辑:

"use client";

import React from "react";

interface ButtonNavigationProps {
  navigateTo: string;
  children: React.ReactNode;
}

const ButtonNavigation: React.FC<ButtonNavigationProps> = ({
  navigateTo,
  children,
}) => {
  const handleScroll = () => {
    const target = document.getElementById(navigateTo);
    if (target) {
      // 手动计算偏移量
      const navbarHeight = document.getElementById("navbar")?.offsetHeight || 130;
      const targetTop = target.getBoundingClientRect().top + window.scrollY - navbarHeight;
      window.scrollTo({
        top: targetTop,
        behavior: "smooth",
      });
    }
  };

  return (
    <button
      onClick={handleScroll}
      className="flex items-center gap-x-2 px-8 py-3"
    >
      {children}
      <svg
        xmlns="http://www.w3.org/2000/svg"
        height="24"
        viewBox="0 -960 960 960"
        width="24"
        fill="currentColor"
      >
        <path d="m560-240-56-58 142-142H160v-80h486L504-662l56-58 240 240-240 240Z" />
      </svg>
    </button>
  );
};

export default ButtonNavigation;

方案4:延迟初始化spy属性

首次加载时不启用spy,等待页面稳定后再开启:

"use client";

import React, { useState, useEffect } from "react";
import { Link } from "react-scroll";

interface ButtonNavigationProps {
  navigateTo: string;
  children: React.ReactNode;
}

const ButtonNavigation: React.FC<ButtonNavigationProps> = ({
  navigateTo,
  children,
}) => {
  const [enableSpy, setEnableSpy] = useState(false);

  useEffect(() => {
    // 延迟100ms启用spy,等待布局稳定
    const timer = setTimeout(() => setEnableSpy(true), 100);
    return () => clearTimeout(timer);
  }, []);

  return (
    <Link
      smooth={true}
      spy={enableSpy}
      isDynamic={true}
      to={navigateTo}
      offset={-130}
      duration={650}
      className="flex items-center gap-x-2 px-8 py-3"
    >
      {children}
      <svg
        xmlns="http://www.w3.org/2000/svg"
        height="24"
        viewBox="0 -960 960 960"
        width="24"
        fill="currentColor"
      >
        <path d="m560-240-56-58 142-142H160v-80h486L504-662l56-58 240 240-240 240Z" />
      </svg>
    </Link>
  );
};

export default ButtonNavigation;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 15:08:11