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

React实现点击组件仅当前项高亮 其余项取消背景色

实现方案

核心问题

当前每个Row组件的激活状态isActive由组件内部独立维护,各个Row之间状态完全隔离,无法感知其他组件的点击行为,因此无法实现互斥高亮效果。
要实现需求只需要遵循React的状态提升原则:将多个组件需要共享的状态上移到最近的共同父组件统一管控。

具体代码实现

1. 改造Row组件

移除Row内部自维护的isActive状态,将激活状态、点击事件回调、唯一标识通过props传入:

const Row = ({ isActive, onRowClick, rowId }) => {
  return (
    <div
      style={{
        backgroundColor: isActive ? 'green' : '#c8c7c5',
        padding: '12px',
        margin: '8px 0',
        cursor: 'pointer'
      }}
      onClick={() => onRowClick(rowId)}
    >
      hello
    </div>
  );
};

2. 改造父组件逻辑

不要提前把渲染完成的React元素存在state中,仅保留列表纯配置数据,由父组件统一维护当前激活项的ID,渲染列表时动态为每个Row传入对应props:

const ListContainer = () => {
  // 仅存储列表项配置,不要预存组件
  const itemsConfig = [
    { id: 'list-1' },
    { id: 'list-2' },
    { id: 'list-3' }
  ];
  // 统一管理当前激活的行ID,初始为null表示无高亮项
  const [activeRowId, setActiveRowId] = React.useState(null);

  // 统一处理行点击逻辑
  const handleRowClick = (clickedId) => {
    setActiveRowId(currentId => {
      // 点击已激活的行则取消高亮,保留原有的二次点击恢复默认的交互
      if (currentId === clickedId) return null;
      // 否则更新激活ID为当前点击项,其余项自动失活
      return clickedId;
    })
  }

  return (
    <div className="list-wrapper">
      {itemsConfig.map(item => (
        <Row
          key={item.id}
          rowId={item.id}
          isActive={activeRowId === item.id}
          onRowClick={handleRowClick}
        />
      ))}
    </div>
  )
}

实现说明

  • 所有Row的激活判断逻辑统一由父组件的activeRowId控制,每次点击任意Row都会触发父组件状态更新,所有Row会根据最新的activeRowId重新计算自身的高亮状态,天然实现互斥效果
  • 提前将<Row />这类React元素存入state/变量的写法不推荐,预创建的组件无法接收动态变化的props,列表场景仅需要存储纯配置数据,在渲染阶段动态生成组件即可
  • 逻辑保留了原有交互:点击已高亮的Row会取消高亮,恢复默认背景

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 13:45:31