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

React侧边栏添加active类后scrollIntoView失效问题排查

React侧边栏添加Active类后滚动功能失效的原因与解决办法

问题描述

我之前做了一个React侧边栏,点击菜单项可以滚动到页面上对应id的div元素,功能一直正常。但最近给选中的菜单项添加active类来高亮显示后,滚动到目标元素的功能突然失效了。以下是我的相关代码:

Sidebar.jsx

import React, { useState} from 'react';
import './Sidebar.scss';
import { SlidebarData } from "./SlidebarData";
import spike from '../../assets/spike_pic.jpg';

const Sidebar = () => {
  const [sideBar, setSidebar] = useState(false);
  const [selectedLink, setSelectedLink] = useState("");

  return (
    <div className="sidebar">
      <span className="btn" onClick={() => setSidebar(!sideBar)}>Menu</span>
      <div className="profile">
        <img src={spike}/>
        <span>Alim Budaev</span>
        <span>Available for work</span>
      </div>
      <ul className="sidebarlist" id={sideBar ? "hidden" : ""}>
        {SlidebarData.map((val,key) =>{
          return (
            <li className={`row ${selectedLink === val.link ? "active" : ""}`} id={val.link} key={key} onClick={()=> {
              setSelectedLink(val.link);
              document.getElementById(val.link).scrollIntoView();
            }}>
              {""}
              <div>
                {val.title}
              </div>
            </li>
          );
        })}
      </ul>
    </div>
  );
}

export default Sidebar;

SlidebarData.jsx

export const SlidebarData = [
  { title: "Home", link: "home" },
  { title: "About", link: "about" },
  { title: "Services", link: "services" },
  { title: "Contact", link: "contact" }
]

问题原因

核心问题出在DOM元素的id唯一性上:你给侧边栏的<li>元素设置了和页面目标div完全相同的id(也就是val.link)。当你点击菜单项时,首先调用setSelectedLink更新状态,组件会重新渲染。此时执行document.getElementById(val.link)时,浏览器会优先找到当前的<li>元素(因为它在DOM树中更靠前),而不是你真正想要滚动到的页面div。所以scrollIntoView()实际上是让页面滚动到了侧边栏的菜单项本身,而不是目标内容区域,看起来就像功能失效了。

解决办法

只需要确保侧边栏的<li>元素和目标div的id不重复即可,有两种简单的实现方式:

方式1:移除<li>的id属性

因为你已经通过selectedLink状态来控制active类的显示,完全不需要给<li>设置id。修改后的<li>代码如下:

<li className={`row ${selectedLink === val.link ? "active" : ""}`} key={key} onClick={()=> {
  setSelectedLink(val.link);
  document.getElementById(val.link).scrollIntoView({ behavior: 'smooth' }); // 可选:添加平滑滚动效果
}}>
  <div>{val.title}</div>
</li>

方式2:给<li>设置唯一的id

如果确实需要给<li>设置id用于其他逻辑,可以给它加个前缀,确保和目标div的id不重复:

<li className={`row ${selectedLink === val.link ? "active" : ""}`} id={`sidebar-${val.link}`} key={key} onClick={()=> {
  setSelectedLink(val.link);
  document.getElementById(val.link).scrollIntoView();
}}>
  <div>{val.title}</div>
</li>

额外优化建议

如果你想更贴合React的开发习惯,避免直接操作DOM,可以使用useRef来引用目标元素。比如在页面的目标div上添加ref,然后通过ref来调用scrollIntoView(),这样代码会更健壮。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 09:22:43