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

React实现对象数组遍历及点击高亮单个列表项问题

解决React列表项点击仅高亮选中项的问题

你遇到的问题很典型——现在你的active状态是一个布尔值,所有列表项都根据这个值来判断是否添加hover类,所以一旦状态切换,所有项都会同时高亮或者取消高亮。要实现“点击哪项哪项高亮,其余保持原样”的效果,我们需要追踪具体选中的项的ID,而不是用一个统一的布尔值。

下面是具体的修改步骤和完整代码:

1. 调整状态结构

把原来的active: false改成selectedId: null,用来存储当前选中项的ID,初始值null表示没有任何项被选中。

2. 更新点击事件处理函数

修改toggleClass方法,点击时判断当前点击的ID是否和selectedId一致:

  • 如果一致,说明是点击了已经高亮的项,把selectedId设为null取消高亮
  • 如果不一致,就把selectedId设为当前点击的ID,让该项高亮

3. 动态判断列表项的类名

在渲染<li>的时候,对比当前项的id和selectedId,相等就添加hover类,否则不添加。

修改后的完整代码

import React, { Component } from 'react';

class MenuSelector extends Component {
  state = {
    selectedId: null, // 改为存储选中的ID
    menu: [
      { id: 1, fighterName: 'Goku', race: 'Sayian', specialAttack: 'Kamehameha Wave', img: 'https://nerdist.com/wp-content/uploads/2018/01/Dragon-Ball-Super-Goku.jpg' },
      { id: 2, fighterName: 'Vegeta', race: 'Sayian', specialAttack: 'Final Flash', img: 'https://imgmr.com/wp-content/uploads/2016/04/Vegeta-SSGSS-2.png' },
      { id: 3, fighterName: 'Gohun', race: 'Human', specialAttack: 'Masenko', img: 'https://techanimate.com/wp-content/uploads/2017/11/Why-does-Gohan-Have-so-much-Hidden-Power-1024x576.jpg' },
      { id: 4, fighterName: 'Krillin', race: 'Human', specialAttack: 'Destructo Disc', img: 'https://static3.srcdn.com/wordpress/wp-content/uploads/2016/09/Krillin-Destructo-Disk.jpg' },
      { id: 5, fighterName: 'Android 17', race: 'Android', specialAttack: 'Barrier', img: 'https://i.ytimg.com/vi/SzAiIy_Dnb4/maxresdefault.jpg' },
      { id: 6, fighterName: 'Jiren', race: 'Unknown', specialAttack: 'Eye Paralysis', img: 'https://vignette.wikia.nocookie.net/dragonuniverse/images/9/9c/Jiren.png/revision/latest/scale-to-width-down/2000?cb=20180211002429' },
      { id: 7, fighterName: 'Lord Beerus', race: 'God', specialAttack: 'Hakai', img: 'https://vignette.wikia.nocookie.net/dragonuniverse/images/3/30/Beerus2.png/revision/latest?cb=20170225064338' },
      { id: 8, fighterName: 'Cell', race: 'Android', specialAttack: 'Kamehameha Wave', img: 'https://static0.srcdn.com/wordpress/wp-content/uploads/Dragon-Ball-Z-Perfect-Cell.jpg' },
      { id: 9, fighterName: 'Frieza', race: 'Unknown', specialAttack: 'Finger Blasters', img: 'https://i.ytimg.com/vi/BkoOw_7JqKg/maxresdefault.jpg' },
      { id: 10, fighterName: 'Black Goku', race: 'Sayian', specialAttack: 'Ki Blade', img: 'https://pm1.narvii.com/6287/eafbdf4dc0ae1b58d3869b89be04bcd0712f7623_hq.jpg' },
    ]
  }

  toggleClass = (id) => {
    console.log(`Clicked item ${id}`);
    // 判断当前点击的ID是否是已选中的
    this.setState(prevState => ({
      selectedId: prevState.selectedId === id ? null : id
    }));
  };

  render() {
    return (
      <div className="container">
        <h1>Menu Selector</h1>
        <div>
          <ul>
            {this.state.menu.map((dragonball) => (
              // 注意:这里用dragonball.id作为key比index更好,避免列表更新时的问题
              <li 
                key={dragonball.id} 
                onClick={() => this.toggleClass(dragonball.id)} 
                className={this.state.selectedId === dragonball.id ? 'hover' : ''}
              >
                <div className="container-dragonball">
                  <div className="dragonball-stats">
                    <h1>{dragonball.fighterName}</h1>
                    <p>Race: {dragonball.race}</p>
                    <p>Special Attack: {dragonball.specialAttack}</p>
                  </div>
                  <div className="dragonball-img">
                    <img src={dragonball.img} alt={dragonball.fighterName} />
                  </div>
                </div>
              </li>
            ))}
          </ul>
        </div>
      </div>
    );
  }
}

export default MenuSelector;

额外优化提示

  • 我把列表项的key从index改成了dragonball.id,这是React列表渲染的最佳实践——因为index会随着列表项的增删改变,而id是唯一且稳定的,能避免不必要的组件重渲染和状态混乱。
  • 如果你的需求是“必须保持有一个项高亮,不能取消”,那只需要把toggleClass里的逻辑改成直接设置selectedId: id,去掉判断是否相等的部分即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 10:12:09