React实现Nike式商品属性单选功能遇useRef取值异常求助
嘿,我来帮你排查这个问题~
你遇到的核心问题是单个useRef无法同时绑定多个循环生成的元素:当你在map循环里把同一个ref绑定到所有radio输入框时,React最终会让这个ref的current指向最后一个被渲染的元素,所以不管你点哪个选项,拿到的都是最后一个radio的值(也就是你说的"M")。
另外还有个小问题:你现在手动操作DOM的classList来切换样式,这其实不符合React的声明式编程思路,更推荐用状态来控制样式变化。
给你两个更合理的解决方案,选哪个都可以:
方案1:用React状态管理选中状态(推荐)
直接用useState来跟踪选中的尺寸,通过状态动态控制样式和radio的选中状态,完全不需要useRef:
import { useState } from 'react'; // 首先定义状态管理选中的尺寸 const [selectedSize, setSelectedSize] = useState(''); // 渲染部分修改成这样 <h1 className="text-center text-2xl">{product.name}</h1> <div> <div className={'block my-3'}> {product.attribute?.map((item, index) => ( <div className={'inline-block'} key={index}> <label className={`cursor-pointer py-2 px-3 my-3 mx-2 border h-3 rounded hover:border-black ${ selectedSize === item.value ? 'border-black' : 'border-grey-500' }`} htmlFor={item.id} > {item.value} </label> <input className="hidden" type="radio" id={item.id} value={item.value} name={'selectSize'} // 用状态控制radio是否选中 checked={selectedSize === item.value} // onChange事件直接更新状态 onChange={(e) => setSelectedSize(e.target.value)} /> </div> ))} </div> </div>
方案2:如果想保留label的点击事件
也可以在循环渲染时,直接把当前选项的value传给点击事件,同样不需要ref:
import { useState } from 'react'; const [selectedSize, setSelectedSize] = useState(''); const labelOnclickHandler = (value) => { setSelectedSize(value); }; // 渲染部分 <h1 className="text-center text-2xl">{product.name}</h1> <div> <div className={'block my-3'}> {product.attribute?.map((item, index) => ( <div className={'inline-block'} key={index}> <label onClick={() => labelOnclickHandler(item.value)} className={`cursor-pointer py-2 px-3 my-3 mx-2 border h-3 rounded hover:border-black ${ selectedSize === item.value ? 'border-black' : 'border-grey-500' }`} htmlFor={item.id} > {item.value} </label> <input className="hidden" type="radio" id={item.id} value={item.value} name={'selectSize'} checked={selectedSize === item.value} // 这里可以保留onChange,也可以去掉,因为点击label已经会触发radio的change事件 onChange={(e) => setSelectedSize(e.target.value)} /> </div> ))} </div> </div>
为什么这样更靠谱?
- 完全遵循React的数据流:状态变化驱动UI更新,避免手动操作DOM带来的潜在bug
- 不需要依赖
useRef,彻底解决了ref指向错误的问题 - 代码更简洁,逻辑更清晰,后续维护起来也更方便
内容的提问来源于stack exchange,提问作者Jud3v Digital
相关产品推荐
相关产品推荐

