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

React列表元素点击样式切换求助:单选及多选样式修改

Fixing React List Item Selection (Single & Multiple)

Hey there! Let's get this sorted out. The issue you're seeing right now is because you're using a single boolean state (colorDefault) to control the style of all list items. When you click any item, you flip that global state, so every element updates its style at the same time—definitely not what you want!

Solution 1: Single Item Selection

First, let's fix the single-selection case, where clicking one item highlights it and unhighlights any previously selected item.

Key Changes:

  • Replace the colorDefault state with a selectedId state that stores the ID of the currently selected item (start with null for no selection).
  • When clicking an item, update selectedId to the clicked item's ID (or clear it if you click the same item again).
  • For each list item, check if its ID matches selectedId to apply the active style.

Updated Code:

const nodes = [ {id: 0, name: 'aaa', parent: null }, {id: 1, name: 'bbb', parent: 0 }, {id: 2, name: 'ccc', parent: 0 }, {id: 3, name: 'ddd', parent: null }, {id: 4, name: 'eee', parent: 3 }, {id: 5, name: 'fff', parent: 3 }, {id: 6, name: 'ggg', parent: 3 }, {id: 7, name: 'hhh', parent: null }, {id: 8, name: 'iii', parent: 7 }, {id: 9, name: 'jjj', parent: 8 }, {id: 10, name: 'kkk', parent: 9 }, {id: 11, name: 'lll', parent: 9 }, {id: 12, name: 'mmm', parent: 9 }, {id: 13, name: 'nnn', parent: 8 }, {id: 14, name: 'ooo', parent: 13 }, {id: 15, name: 'ppp', parent: 13 }, {id: 16, name: 'qqq', parent: 13 }, {id: 17, name: 'rrr', parent: null }, {id: 18, name: 'sss', parent: 17 }, {id: 19, name: 'ttt', parent: 17 }, {id: 20, name: 'uuu', parent: 19 }, {id: 21, name: 'vvv', parent: 19 }, {id: 22, name: 'www', parent: 17 }, {id: 23, name: 'xxx', parent: 17 }, {id: 24, name: 'yyy', parent: 23 }, {id: 25, name: 'zzz', parent: 23 } ];

class App extends React.Component {
  constructor(){
    super();
    // Track the selected item's ID instead of a global boolean
    this.state = { selectedId: null }
  }

  handleSelect = (id) => {
    // Toggle selection: if same item is clicked, clear selection
    this.setState(prevState => ({
      selectedId: prevState.selectedId === id ? null : id
    }));
  }

  render(){
    const nodeColorBlue = {color: '#00f'};
    const nodeColorDefault = {color: '#000'};

    const renderNodes = nodes.map(node => {
      // Apply blue style only if this node's ID matches selectedId
      const itemStyle = node.id === this.state.selectedId ? nodeColorBlue : nodeColorDefault;
      return (
        <li 
          key={node.id} 
          style={itemStyle} 
          onClick={() => this.handleSelect(node.id)}
        > 
          {node.name} 
        </li> 
      );
    });

    return ( 
      <div className="App"> 
        <ul>{renderNodes}</ul> 
      </div> 
    )
  }
}

export default App;

Solution 2: Multiple Item Selection

For selecting multiple items (toggle selection on click), we'll use a Set to track all selected IDs—Sets make adding/removing items quick and efficient.

Key Changes:

  • Use a selectedIds state initialized as an empty Set.
  • On click, toggle the ID in the Set: if it's already present, remove it; if not, add it.
  • Check if the current node's ID is in the selectedIds Set to apply the active style.

Updated Code:

const nodes = [ {id: 0, name: 'aaa', parent: null }, {id: 1, name: 'bbb', parent: 0 }, {id: 2, name: 'ccc', parent: 0 }, {id: 3, name: 'ddd', parent: null }, {id: 4, name: 'eee', parent: 3 }, {id: 5, name: 'fff', parent: 3 }, {id: 6, name: 'ggg', parent: 3 }, {id: 7, name: 'hhh', parent: null }, {id: 8, name: 'iii', parent: 7 }, {id: 9, name: 'jjj', parent: 8 }, {id: 10, name: 'kkk', parent: 9 }, {id: 11, name: 'lll', parent: 9 }, {id: 12, name: 'mmm', parent: 9 }, {id: 13, name: 'nnn', parent: 8 }, {id: 14, name: 'ooo', parent: 13 }, {id: 15, name: 'ppp', parent: 13 }, {id: 16, name: 'qqq', parent: 13 }, {id: 17, name: 'rrr', parent: null }, {id: 18, name: 'sss', parent: 17 }, {id: 19, name: 'ttt', parent: 17 }, {id: 20, name: 'uuu', parent: 19 }, {id: 21, name: 'vvv', parent: 19 }, {id: 22, name: 'www', parent: 17 }, {id: 23, name: 'xxx', parent: 17 }, {id: 24, name: 'yyy', parent: 23 }, {id: 25, name: 'zzz', parent: 23 } ];

class App extends React.Component {
  constructor(){
    super();
    // Use a Set to track multiple selected IDs
    this.state = { selectedIds: new Set() }
  }

  handleToggleSelect = (id) => {
    this.setState(prevState => {
      const newSelectedIds = new Set(prevState.selectedIds);
      if (newSelectedIds.has(id)) {
        newSelectedIds.delete(id);
      } else {
        newSelectedIds.add(id);
      }
      return { selectedIds: newSelectedIds };
    });
  }

  render(){
    const nodeColorBlue = {color: '#00f'};
    const nodeColorDefault = {color: '#000'};

    const renderNodes = nodes.map(node => {
      // Apply blue style if the node's ID is in the selectedIds Set
      const itemStyle = this.state.selectedIds.has(node.id) ? nodeColorBlue : nodeColorDefault;
      return (
        <li 
          key={node.id} 
          style={itemStyle} 
          onClick={() => this.handleToggleSelect(node.id)}
        > 
          {node.name} 
        </li> 
      );
    });

    return ( 
      <div className="App"> 
        <ul>{renderNodes}</ul> 
      </div> 
    )
  }
}

export default App;

Quick Notes:

  • I switched to arrow functions for event handlers to avoid needing .bind(this)—it's a cleaner approach in class components.
  • For multiple selection, you could also use an array instead of a Set, but Sets are better for checking membership (has() runs in constant time, vs array includes() which checks every element).

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 08:37:31