
本文介绍如何使用 react 的 usestate 管理单选式激活状态,使点击任意元素容器时高亮当前项(变红 + 显示“active”),同时自动重置其他项,并确保子菜单按钮点击不触发状态变更。
本文介绍如何使用 react 的 usestate 管理单选式激活状态,使点击任意元素容器时高亮当前项(变红 + 显示“active”),同时自动重置其他项,并确保子菜单按钮点击不触发状态变更。
在构建交互式列表组件时,常需实现「单选高亮」效果:用户点击某一项,该项视觉激活(如边框变红、文字变为 "Active"),其余项恢复默认;且该行为应严格限定于目标区域,避免误触子元素(如按钮)引发意外状态切换。
核心思路是:用一个 state 变量(如 active)记录当前被选中的 ID,通过条件渲染控制样式与内容,并利用事件冒泡机制的天然特性——只要不阻止传播,父级 onClick 会捕获子元素点击;但关键在于:我们只将 onClick 绑定在需要响应点击的容器上,而非按钮本身。
以下是优化后的完整实现:
import { useState } from "react";
import "./styles.css";
const data = [
{ id: "1", title: "first element" },
{ id: "2", title: "second element" },
{ id: "3", title: "third element" },
];
export default function App() {
const [active, setActive] = useState(null);
return (
<div id="main" classname="App">
{data.map((item) => (
<div key="{item.id}">
{/* 只对此 div 绑定 onClick,button 不处理 */}
<div classname="{`item" item.id : onclick="{()"> setActive(item.id)}
>
{active === item.id ? "Active" : item.title}
</div>
<button>submenu</button>
</div>
))}
</div>
);
}
配套 CSS 示例(styles.css):
.App {
padding: 16px;
}
.item {
padding: 12px;
margin: 8px 0;
border: 2px solid #ccc;
border-radius: 4px;
cursor: pointer;
transition: all 0.2s ease;
}
.item.active {
border-color: red;
background-color: #fff5f5;
}
button {
margin-left: 8px;
padding: 6px 12px;
border: 1px solid #999;
background: #f9f9f9;
cursor: pointer;
}
✅ 关键要点说明:
- 使用
key={item.id}确保列表渲染稳定性,避免潜在重渲染异常; -
active === item.id采用严格相等判断,防止类型隐式转换导致误匹配; - 激活态文案统一显示为
"Active"(首字母大写、全大写更符合 UI 规范),非激活态显示原始title; -
submenu按钮未绑定任何状态逻辑,因此点击它不会改变active,也不会触发父级div的onClick—— 因为其自身是独立可点击元素,且未调用event.stopPropagation(),但因onClick仅注册在外层div上,按钮点击自然不触发该 handler(除非你主动给 button 加了onClick并调用了setActive()); - 若未来需支持键盘导航(如 Enter/Space 触发),可在
div上添加role="button"和tabIndex={0},进一步提升可访问性。
该方案简洁、健壮、可扩展,适用于任意数量的同类选项,是 React 中管理互斥激活状态的标准实践。










