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

React侧边栏选中项activeClassName高亮不生效如何修复

问题描述

开发带侧边栏的React应用时,整体展示效果正常,但点击侧边栏菜单项后,无法正确给已访问的页面链接标记选中高亮状态。
已经在SidebarLink组件上添加了activeClassName="selected"属性,也在对应的styled-components样式里写了.selected类的样式规则,但选中高亮始终不触发。

问题代码

import React, { useState } from "react";
import { Link } from "react-router-dom";
import styled from "styled-components";

const SidebarLink = styled(Link)`
  /*border: 3px solid green;*/
  display: flex;
  color: #e1e9fc;
  justify-content: space-between;
  align-items: center;
  padding: 20px;
  list-style: none;
  height: 60px;
  text-decoration: none;
  font-size: 18px;
  
  &:hover {
    background: #252831;
    border-left: 4px solid #ffbc2e;
    cursor: pointer;
  }

  .selected {
    color: red;
  }
`;
  
const SidebarLabel = styled.span`
  margin-left: 16px;
`;

/* Used for Training dropdown */
const DropdownLink = styled(Link)`
  /*border: 3px solid red;*/
  background: #252831;
  height: 60px;
  padding-left: 3rem;
  display: flex;
  align-items: center;
  text-decoration: none;
  color: #f5f5f5;
  font-size: 16px;
  font-weight: bold;
  
  &:hover {
    background: #48526F;
    border-left: 4px solid #ffbc2e;
    cursor: pointer;
  }
`;

const SubMenu = ({ item }) => {
  const [subnav, setSubnav] = useState(false);
  
  const showSubnav = () => setSubnav(!subnav);
  
  return (
    <>
      <SidebarLink to={item.path} onClick={item.subNav && showSubnav} activeClassName="selected" exact>
        <div className="sidebarTextContainer">
          <div className="sidebarIcon">{item.icon}</div>
          <div className="sidebarText"><SidebarLabel>{item.title}</SidebarLabel></div>
        </div>
        <div>
          {item.subNav && subnav
            ? item.iconOpened
            : item.subNav
            ? item.iconClosed
            : null}
        </div>
      </SidebarLink>
      {subnav &&
        item.subNav.map((item, index) => {
          return (
              <DropdownLink to={item.path} key={index}>
                {item.icon}
                <SidebarLabel>{item.title}</SidebarLabel>
              </DropdownLink>
          );
        })}
    </>
  );
};
  
export default SubMenu;
问题原因
  • styled-components里写的.selected是后代选择器,只会匹配SidebarLink内部class为selected的子元素,但activeClassName是直接加在SidebarLink本身(最终渲染的a标签)上的,选择器写法错误导致样式不生效。
  • 如果使用React Router v6及以上版本,普通Link组件已经移除了activeClassName属性,需要用专门处理导航激活状态的NavLink组件才能实现选中效果。
修复方案
  1. 从react-router-dom导入时把Link替换为NavLink,v6版本的NavLink支持通过回调函数判断当前路由是否激活,给激活状态的链接绑定自定义类名。
  2. 修正styled-components里的选中样式选择器,用&.selected匹配组件自身带selected类的状态,不要写后代选择器。
  3. 子菜单的DropdownLink如果需要选中高亮,同步替换为NavLink并添加对应激活样式即可。

修复后代码

import React, { useState } from "react";
// 替换Link为NavLink
import { NavLink } from "react-router-dom";
import styled from "styled-components";

const SidebarLink = styled(NavLink)`
  /*border: 3px solid green;*/
  display: flex;
  color: #e1e9fc;
  justify-content: space-between;
  align-items: center;
  padding: 20px;
  list-style: none;
  height: 60px;
  text-decoration: none;
  font-size: 18px;
  
  &:hover {
    background: #252831;
    border-left: 4px solid #ffbc2e;
    cursor: pointer;
  }

  /* &代表当前组件自身,匹配自身带selected类的状态 */
  &.selected {
    color: red;
    background: #252831;
    border-left: 4px solid #ffbc2e;
  }
`;
  
const SidebarLabel = styled.span`
  margin-left: 16px;
`;

/* Used for Training dropdown */
const DropdownLink = styled(NavLink)`
  /*border: 3px solid red;*/
  background: #252831;
  height: 60px;
  padding-left: 3rem;
  display: flex;
  align-items: center;
  text-decoration: none;
  color: #f5f5f5;
  font-size: 16px;
  font-weight: bold;
  
  &:hover {
    background: #48526F;
    border-left: 4px solid #ffbc2e;
    cursor: pointer;
  }

  /* 子菜单项选中样式 */
  &.selected {
    color: #ffbc2e;
    background: #48526F;
  }
`;

const SubMenu = ({ item }) => {
  const [subnav, setSubnav] = useState(false);
  
  const showSubnav = () => setSubnav(!subnav);
  
  return (
    <>
      <SidebarLink 
        to={item.path} 
        onClick={item.subNav && showSubnav}
        // v6版本通过className回调设置激活类名,v5版本可直接保留activeClassName="selected"
        className={({isActive}) => isActive ? "selected" : ""}
        end
      >
        <div className="sidebarTextContainer">
          <div className="sidebarIcon">{item.icon}</div>
          <div className="sidebarText"><SidebarLabel>{item.title}</SidebarLabel></div>
        </div>
        <div>
          {item.subNav && subnav
            ? item.iconOpened
            : item.subNav
            ? item.iconClosed
            : null}
        </div>
      </SidebarLink>
      {subnav &&
        item.subNav.map((item, index) => {
          return (
              <DropdownLink 
                to={item.path} 
                key={index}
                className={({isActive}) => isActive ? "selected" : ""}
              >
                {item.icon}
                <SidebarLabel>{item.title}</SidebarLabel>
              </DropdownLink>
          );
        })}
    </>
  );
};
  
export default SubMenu;

补充说明:如果还在使用React Router v5版本,不需要替换Link为NavLink,只需要把样式里的.selected改成&.selected即可正常触发选中效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 15:45:42