如何在React中正确管理Shadcn Toggle组件的单选状态?
问题分析与解决方法
你的问题根源在于Shadcn Toggle组件的onPressedChange事件会在组件pressed状态变化时触发(无论从false变true还是true变false),而你当前的处理逻辑是只要触发事件就直接设置对应状态,导致点击非默认Toggle时出现状态来回覆盖的情况:
- 点击目标Toggle时,它的pressed变为
true,触发onPressedChange,状态被设置为对应类型 - 此时默认Toggle(stroke-none)的pressed从
true变为false,触发它的onPressedChange,状态又被改回stroke-none - 最终状态来回跳动,视觉上无法正确切换激活状态,日志也会先后输出两次不同的值
解决方法
修改onPressedChange的处理逻辑,仅当Toggle被激活(isPressed为true)时才更新状态,避免非激活状态变化时的无效状态更新。
修改后的代码
首先调整每个Toggle的onPressedChange回调:
type StrokeToggleType = "stroke-none" | "stroke-solid" | "stroke-dash-1" | "stroke-dash-2"; const [strokeToggle, setStrokeToggle] = useState<StrokeToggleType>("stroke-none"); const handleToggleChange = (type: StrokeToggleType) => { setStrokeToggle(type); }; // 可优化:将选项配置为数组,减少重复代码 const strokeOptions = [ { type: "stroke-none", icon: <AiOutlineStop className='w-[56px] h-[40px]' /> }, { type: "stroke-solid", icon: <GoDash className='w-[56px] h-[40px]' /> }, { type: "stroke-dash-1", icon: <CgBorderStyleDashed className='w-[56px] h-[40px]' /> }, { type: "stroke-dash-2", icon: <AiOutlineSmallDash className='w-[56px] h-[40px]' /> }, ]; return ( <div className='flex justify-between'> {strokeOptions.map(option => ( <Toggle key={option.type} aria-label={option.type} pressed={strokeToggle === option.type} // 仅在激活时更新状态 onPressedChange={(isPressed) => isPressed && handleToggleChange(option.type)} > {option.icon} </Toggle> ))} </div> );
原理说明
通过判断onPressedChange传递的isPressed参数,只在Toggle被用户点击激活(变为true)时才更新状态,而其他Toggle因状态变化变为非激活时,不会触发无效的状态重置,从而保证单选逻辑的正确性,视觉上也能正确显示当前激活的Toggle。
内容的提问来源于stack exchange,提问作者MInH THiỆn
相关产品推荐
相关产品推荐

