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

React中Bulma下拉菜单动态切换is-active状态的最优实现

实现方案

核心思路

完全不需要为每个菜单项单独创建useState,用一个状态变量记录当前激活菜单项的唯一标识(比如自定义ID)即可。渲染时对比每个项的标识与状态值,动态添加is-active类;同时保留下拉菜单的展开/收起状态管理,逻辑清晰且易维护。

完整代码实现

import React, { useState } from 'react';

const Dropdown = () => {
    // 控制下拉菜单的展开/收起状态
    const [dropdownOpen, setDropdownOpen] = useState(false);
    // 记录当前激活的菜单项ID,初始值设为默认激活项的ID
    const [activeItemId, setActiveItemId] = useState('item-3');

    // 切换下拉菜单显示状态
    const toggleDropdown = (event) => {
        event.preventDefault();
        setDropdownOpen(prev => !prev);
    };

    // 统一处理菜单项点击:设置激活项,可选关闭下拉菜单
    const handleItemClick = (itemId, event) => {
        event.preventDefault();
        setActiveItemId(itemId);
        // 可选:点击菜单项后自动关闭下拉
        setDropdownOpen(false);
    };

    // 把菜单项数据抽成数组,避免重复编写JSX,后续修改更方便
    const dropdownItems = [
        { id: 'item-1', label: 'Dropdown item', href: '#' },
        { id: 'item-2', label: 'Other dropdown item', href: '#' },
        { id: 'item-3', label: 'Active dropdown item', href: '#' },
        { id: 'item-4', label: 'Other dropdown item', href: '#' },
        { id: 'divider', type: 'divider' },
        { id: 'item-5', label: 'With a divider', href: '#' },
    ];

    return (
        <div className={`dropdown ${dropdownOpen ? 'is-active' : ''}`}>
            <div className="dropdown-trigger">
                <button className="button" 
                        aria-haspopup="true"
                        aria-controls="dropdown-menu"
                        onClick={toggleDropdown}>
                    <span>Dropdown button</span>
                    <span className="icon is-small">
                        <i className="fas fa-angle-down" aria-hidden="true"></i>
                    </span>
                </button>
            </div>
            <div className="dropdown-menu" id="dropdown-menu" role="menu">
                <div className="dropdown-content">
                    {dropdownItems.map(item => {
                        // 渲染分隔线
                        if (item.type === 'divider') {
                            return <hr key={item.id} className="dropdown-divider" />;
                        }
                        // 动态判断是否添加is-active类
                        const itemClass = `dropdown-item ${activeItemId === item.id ? 'is-active' : ''}`;
                        return (
                            <a
                                key={item.id}
                                href={item.href}
                                className={itemClass}
                                onClick={(e) => handleItemClick(item.id, e)}
                            >
                                {item.label}
                            </a>
                        );
                    })}
                </div>
            </div>
        </div>
    )    
}

export default Dropdown;

关键细节说明

  1. 数据化管理菜单项:把所有下拉项(包括分隔线)整理成数组,后续新增、修改或删除菜单项只需调整数组,无需重复修改JSX结构,维护成本更低。
  2. 单个状态控制激活项:用activeItemId记录当前激活项的唯一标识,点击菜单项时仅更新该状态,渲染时通过简单的条件判断动态添加is-active类,完全避免了多状态的冗余。
  3. 状态职责分离:将下拉展开/收起的状态(dropdownOpen)与菜单项激活状态(activeItemId)分开管理,逻辑边界清晰,也能灵活控制交互(比如是否点击菜单项后关闭下拉)。
  4. 统一事件处理:用handleItemClick函数处理所有菜单项的点击事件,减少重复代码,后续扩展逻辑(比如路由跳转)也只需修改这一个函数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 15:02:53