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

React中如何用单个onClick事件处理多布尔状态控制侧边栏下拉菜单

问题原因

你之前的复用写法失效核心原因是对象键名的语法问题:你直接在setState的对象里写value作为键,JS会把它解析为固定的字符串键"value",而不是你传入的动态变量,所以实际上你每次更新的都是状态里不存在的value字段,原有菜单的状态完全没被修改,自然不会生效。

最小改动修复方案

只需要把对象键名换成ES6的计算属性名语法,用方括号包裹动态变量即可,同时推荐用函数式更新状态的写法,避免闭包导致的状态更新异常:

const clickHandler = (key, e) => {
  e.preventDefault();
  setState(prevState => ({
    ...prevState,
    [key]: !prevState[key]
  }));
};

渲染部分的调用方式调整为传入对应状态的键名字符串即可:

<div onClick={(e) => clickHandler('one', e)}>First</div>
{state.one && <div>Something</div>}
<div onClick={(e) => clickHandler('two', e)}>Second</div>
{state.two && <div>Something</div>}

注意这里传入的是字符串形式的键名'one',不是变量one,同时要把事件对象e透传给处理函数。

更简洁的全复用方案

如果想彻底消除重复代码,可以把所有菜单的配置抽成数组,遍历渲染,后续新增/修改菜单只需要调整配置数组即可:

// 菜单配置,可任意扩展
const menuList = [
  { id: 'one', title: 'First', content: 'First menu content' },
  { id: 'two', title: 'Second', content: 'Second menu content' },
  { id: 'three', title: 'Third', content: 'Third menu content' },
  { id: 'four', title: 'Fourth', content: 'Fourth menu content' },
  { id: 'five', title: 'Fifth', content: 'Fifth menu content' },
  { id: 'six', title: 'Sixth', content: 'Sixth menu content' },
]

function Sidebar() {
  const [openState, setOpenState] = useState({
    one: false,
    two: false,
    three: false,
    four: false,
    five: false,
    six: false,
  });

  const toggleMenu = (menuId, e) => {
    e.preventDefault();
    setOpenState(prev => ({
      ...prev,
      [menuId]: !prev[menuId]
    }));
  };

  return (
    <div className="sidebar">
      {menuList.map(menu => (
        <div key={menu.id} className="menu-item">
          <div className="menu-title" onClick={(e) => toggleMenu(menu.id, e)}>
            {menu.title}
          </div>
          {openState[menu.id] && <div className="menu-content">{menu.content}</div>}
        </div>
      ))}
    </div>
  )
}

可选优化:手风琴模式

如果你需要实现「每次只展开一个菜单」的手风琴效果,可以直接把状态改成存储当前展开的菜单ID,不用存储6个布尔值,代码更简洁:

const [activeMenuId, setActiveMenuId] = useState(null);

const toggleMenu = (menuId, e) => {
  e.preventDefault();
  // 如果点击的是已经展开的菜单就收起,否则切换为当前点击的菜单
  setActiveMenuId(prev => prev === menuId ? null : menuId);
};

// 渲染时判断逻辑改为
{activeMenuId === menu.id && <div className="menu-content">{menu.content}</div>}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 09:15:04