如何在点击数组元素时使用useState仅修改被点击元素?
问题与代码
你的原始代码如下:
// Using a boolean data type as state const [layerOne, setLayerOne] = useState(false) // Looping three elements and I want to modify only the element that I click {[1, 2, 3].map((o, i) => ( <div key={i} id={`opt-${i}`} className="option" onClick={() => setLayerOne(!layerOne)} > {layerOne ? <BsEyeSlashFill size={21} /> : <BsEyeFill size={21} />} <div className="option__tittle"> {layerOne ? 'hide' : 'show'} layer </div> </div> ))}
你希望点击列表中的某个元素时,仅修改该元素的状态,而非全部元素一起切换,打算为每个项设置独立的布尔状态,该如何实现?
解决方案
你当前的问题在于用单个布尔值layerOne共享控制所有元素的状态,所以点击任何一个都会触发全局切换。要实现独立控制,需要用数组或对象来存储每个元素的独立状态,以下是两种可行方式:
方式一:用数组存储状态(适合固定长度的列表)
直接用数组对应每个元素的状态,索引和map的下标一一对应:
// 初始化数组,长度和列表元素数量一致,初始值全为false const [layerStates, setLayerStates] = useState([false, false, false]) {[1, 2, 3].map((o, i) => ( <div key={i} id={`opt-${i}`} className="option" onClick={() => { // 复制原数组,避免直接修改state(React要求不可变更新) const updatedStates = [...layerStates]; // 切换当前点击元素对应的状态 updatedStates[i] = !updatedStates[i]; setLayerStates(updatedStates); }} > {/* 根据当前索引对应的状态渲染图标和文字 */} {layerStates[i] ? <BsEyeSlashFill size={21} /> : <BsEyeFill size={21} />} <div className="option__tittle"> {layerStates[i] ? 'hide' : 'show'} layer </div> </div> ))}
方式二:用对象存储状态(适合动态长度的列表)
如果你的列表是动态生成的(比如元素数量不固定),用对象存储更灵活,键可以用元素的唯一标识(这里用索引):
// 初始化为空对象,后续动态添加每个元素的状态 const [layerStates, setLayerStates] = useState({}) {[1, 2, 3].map((o, i) => ( <div key={i} id={`opt-${i}`} className="option" onClick={() => { // 函数式更新,确保拿到最新的state setLayerStates(prevStates => ({ ...prevStates, // 切换当前元素的状态,未初始化时默认是false,!undefined会转为true [i]: !prevStates[i] })) }} > {/* 用空值合并运算符处理未初始化的状态,默认显示show状态 */} {layerStates[i] ?? false ? <BsEyeSlashFill size={21} /> : <BsEyeFill size={21} />} <div className="option__tittle"> {layerStates[i] ?? false ? 'hide' : 'show'} layer </div> </div> ))}
内容的提问来源于stack exchange,提问作者Aurelio Martín
相关产品推荐
相关产品推荐

