React实现单选按钮组:点击选中一个其余取消选中问题排查
问题根源与修复方案
你的代码里有几个关键问题导致状态滞后:
- switch语句穿透:
handleClick里的每个case都没加break,不管点击哪个按钮,最终都会执行到case 2的逻辑,等于每次点击都会强制选中第三个按钮。 - 异步状态的错误使用:
changeColour中调用setColour后立刻读取colour系列变量,但React的setState是异步的,此时拿到的还是更新前的旧值,导致给DOM添加类名时用了旧状态,显示滞后。 - 冗余状态+直接操作DOM:同时维护多组状态(colour系列和backgroundColor系列),还手动修改DOM的className,违背了React状态驱动UI的原则,极易出现状态与DOM不一致的情况。
优化后的代码
我们可以简化状态管理,只用一个变量记录选中按钮的索引,完全通过状态驱动UI渲染:
import React from "react"; import '../output.css' import Images from "./Images"; import { ImageLogo as Img } from "./Images"; export default function Events() { const buttonColour = "bg-red-700"; // 用单个状态记录选中的按钮索引,初始为null表示未选中 const [selectedIndex, setSelectedIndex] = React.useState<number | null>(null); const handleClick = (index: number) => { // 点击时直接设置选中索引,自动覆盖之前的选中状态 setSelectedIndex(index); }; // 根据索引动态生成按钮类名 const getButtonClass = (index: number) => { const baseClass = "w-1.5/12 text-center h-4/6 hover:bg-red-700 rounded-md"; return selectedIndex === index ? `${baseClass} ${buttonColour}` : baseClass; }; return ( <div> <h1 className="text-white font-bold text-center">EVENT SCHEDULE</h1> <div className="Dates flex text-yellow-800 font-bold justify-center h-15-s"> <p className={getButtonClass(0)} onClick={() => handleClick(0)} > January 10th </p> <p className={getButtonClass(1)} onClick={() => handleClick(1)} > January 11th </p> <p className={getButtonClass(2)} onClick={() => handleClick(2)} > January 12th </p> </div> {/* 根据选中索引渲染对应组件 */} {selectedIndex === 0 && <Images />} {selectedIndex === 1 && <Img />} {selectedIndex === 2 && <Img />} </div> ); }
优化说明
- 简化状态管理:只用
selectedIndex一个状态变量,统一管理所有按钮的选中状态,避免多状态同步出错。 - 状态驱动UI:完全通过状态判断来生成类名,不再手动操作DOM,确保状态与DOM显示始终一致。
- 移除冗余代码:删除了无用的ref、多组重复状态和复杂的DOM操作逻辑,代码更简洁易维护。
内容的提问来源于stack exchange,提问作者Saurav Chittal
相关产品推荐
相关产品推荐

