React点击图片切换类名失效:数组元素无法移除的修复方法
问题分析与修复方案
核心问题
你的代码存在两个关键错误,导致无法正常移除数组中的索引:
- 直接修改React状态数组:
let returnArray = prevState是引用赋值,修改returnArray等同于直接修改原状态,违反了React状态不可变的原则,会导致状态更新异常。 - splice返回值误用:
splice方法执行后返回的是被删除元素组成的数组,而非修改后的原数组。删除操作时返回的是仅包含被删索引的数组,而非剩余元素的数组,直接导致后续状态判断失效。 - Strict Mode放大问题:Strict Mode下React会双重调用setState的更新函数,直接修改原状态的行为会被放大,引发更明显的异常;关闭Strict Mode后,状态更新逻辑的错误依然存在,导致当前点击项无法正确移除。
修复后的代码方案
方案一:使用filter生成新数组(简洁推荐)
function toggleFavoriteChanel(index) { setFavorite(prevState => { if (prevState.includes(index)) { // 过滤掉当前索引,返回全新数组 return prevState.filter(item => item !== index); } else { // 新增索引,扩展原数组生成新数组 return [...prevState, index]; } }); }
方案二:复制原数组后修改(直观易理解)
function toggleFavoriteChanel(index) { setFavorite(prevState => { // 先复制原数组,避免修改原状态 const newFavorite = [...prevState]; const idx = newFavorite.indexOf(index); if (idx !== -1) { // 删除对应索引 newFavorite.splice(idx, 1); } else { // 添加新索引 newFavorite.push(index); } // 返回修改后的新数组 return newFavorite; }); }
进阶优化建议
用数组索引作为key和存储标识存在隐患:如果visibleData数组发生增删、排序变化,索引会随之改变,导致组件复用异常或收藏状态错位。建议改用每个频道的唯一ID(比如chanel.id)替代索引:
// 修改收藏函数,存储频道ID function toggleFavoriteChanel(chanelId) { setFavorite(prevState => { if (prevState.includes(chanelId)) { return prevState.filter(id => id !== chanelId); } else { return [...prevState, chanelId]; } }); } // 渲染部分调整 {Array.isArray(props.visibleData) ? props.visibleData.map((chanel, index) => { return ( <div className="chanel__item" key={chanel.id}> <img src={star} alt="star" onClick={() => props.toggleFavoriteChanel(chanel.id)} id={chanel.id} className={`star ${props.favorite.includes(chanel.id) ? 'active' : ''}`} /> <NavLink onClick={() => props.updateData(index)} end style={{ textDecoration: 'none' }} to='/ChanelPage'> <img src={chanel.image} alt="" className="chanel__img" /> <div className="chanel__title"> <div className="chanel__item-number">{index + 1}. </div> {chanel.name_ru} </div> </NavLink> </div> ) }) : null}
内容的提问来源于stack exchange,提问作者Даниил Владимиров
相关产品推荐
相关产品推荐

