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

React Hooks实现点击行切换背景色仅单行高亮方案

问题背景

接触React JS时间较短,需要实现列表行点击背景色切换效果,交互要求如下:

  • 点击单行时该行背景变为红色,再次点击同一行则背景恢复白色
  • 点击新行时,其余所有行自动重置为默认白色背景,始终最多只有一行是红色状态
    当前编写的代码可运行,但存在点击多行时多行同时变红的异常,不符合预期。原有问题代码如下:
import { useState } from "react";

export default function App() {
  const [color, setColor] = useState("white");

  const handleClick = (e) => {

    const value_color = e.target.style.backgroundColor;

    if (value_color != "" && value_color != undefined) {
      if (value_color === "white") 
        var new_color = "red";
      else 
        var new_color = "white";
    }

    setColor("white");
    e.target.style.backgroundColor = new_color;

  };

  return (
    <div>
      <div
        id={"line1_id"}
        style={{
          backgroundColor: color
        }}
        onClick={handleClick}
      >
        First Line
      </div>

      <div
        id={"line2_id"}
        style={{
          backgroundColor: color
        }}
        onClick={handleClick}
      >
        Second Line
      </div>
    </div>
  );
}
问题根因

原有代码的问题出在两个地方:

  • 违反React 状态驱动视图的核心原则,直接通过e.target.style手动修改DOM样式,这部分修改不受React状态管控,状态触发重渲染时不会清理手动添加的样式,自然会出现多行红色残留
  • 只用了一个全局color状态绑定所有行的背景色,没有记录当前选中行的唯一标识,无法区分不同行的选中状态
修复实现

不要手动操作DOM,用单一状态记录当前激活行的唯一ID即可,修复后代码:

import { useState } from "react";

export default function App() {
  // 存储当前激活行的ID,null表示无选中行
  const [activeLineId, setActiveLineId] = useState(null);

  const handleClick = (lineId) => {
    // 点击已选中行则取消选中,所有行回到白色
    if (activeLineId === lineId) {
      setActiveLineId(null);
      return;
    }
    // 点击新行则更新激活ID,其余行自动重置为白色
    setActiveLineId(lineId);
  };

  return (
    <div>
      <div
        id="line1_id"
        style={{
          backgroundColor: activeLineId === "line1_id" ? "red" : "white"
        }}
        onClick={() => handleClick("line1_id")}
      >
        First Line
      </div>

      <div
        id="line2_id"
        style={{
          backgroundColor: activeLineId === "line2_id" ? "red" : "white"
        }}
        onClick={() => handleClick("line2_id")}
      >
        Second Line
      </div>
    </div>
  );
}
逻辑说明
  • 所有样式完全由状态驱动,没有任何手动DOM操作,不存在样式残留问题
  • 重渲染时会逐行判断当前行ID是否和激活ID匹配,匹配则显示红色,否则显示白色,天然满足“点击新行其余行自动变白”的要求
  • 点击已选中的行时,将激活ID设为null,即可实现再次点击取消选中、背景恢复白色的效果
  • 后续新增行只需要分配唯一ID、复用相同的判断逻辑即可,扩展性更好

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 22:57:22