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
相关产品推荐
相关产品推荐

