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

React中如何通过上下方向键切换下拉菜单选项的active类

React下拉菜单方向键切换选中状态解决方案

原代码核心问题

  • 按键判断逻辑错误:e.key === 38 || e.key === 40混淆了keyCode和key属性的用法,方向键上的e.key值为ArrowUp、下为ArrowDown,38、40是已经废弃的e.keyCode属性值
  • 事件绑定对象错误:li标签默认不可聚焦,按键事件无法触发到li元素上,事件应该绑定到全局或者下拉外层容器
  • 无方向切换逻辑:原代码没有区分上下方向的移动逻辑,只是粗暴替换当前active类,无法实现上下遍历
  • 类名拼接错误:this.className += "active"没有加空格,会导致类名拼接为list-itemactive,无法匹配active样式
  • useEffect缺少依赖项:无依赖的useEffect会在每次组件渲染后重复执行,导致事件重复绑定,且未处理下拉关闭时的事件解绑,会造成内存泄漏
  • 重复设置默认选中:循环内多次给第一个元素加active类,属于无效冗余逻辑

修复后的实现方案(符合React最佳实践,不直接操作DOM)

1. 新增状态管理选中索引

// 新增activeIndex状态,默认值0对应第一个选项
const [activeIndex, setActiveIndex] = useState(0);
// 原有状态保留
const [open, setOpen] = useState(false);
const [selected, setSelected] = useState("");
const options = ["Option1", "Option2", "Option3", "Option4"];

2. 新增键盘事件监听useEffect

useEffect(() => {
  // 只有下拉打开时才绑定键盘事件
  if (!open) return;
  // 每次打开下拉重置选中索引为第一个
  setActiveIndex(0);

  const handleKeyDown = (e) => {
    if (e.key === 'ArrowDown') {
      // 阻止默认页面滚动
      e.preventDefault();
      setActiveIndex(prev => prev < options.length - 1 ? prev + 1 : prev);
    } else if (e.key === 'ArrowUp') {
      e.preventDefault();
      setActiveIndex(prev => prev > 0 ? prev - 1 : prev);
    } else if (e.key === 'Enter') {
      // 可选功能:按回车选中当前项
      setSelected(options[activeIndex]);
      setOpen(false);
    }
  }

  window.addEventListener('keydown', handleKeyDown);
  // 卸载/下拉关闭时移除事件监听
  return () => window.removeEventListener('keydown', handleKeyDown);
}, [open, options.length, activeIndex])

3. 修改下拉列表渲染逻辑,动态绑定active类

{open && (
  <ul className="list" id="lists">
    {options.map((option, i) => (
      <li
        onClick={() => {
          setSelected(option);
          setOpen(false);
        }}
        {/* 动态判断是否添加active类 */}
        className={`list-item ${i === activeIndex ? 'active' : ''}`}
        key={i}
      >
        {option}
      </li>
    ))}
  </ul>
)}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 03:45:06