点击事件渲染状态变量时删除最后添加元素异常求助
问题场景与代码实现
状态变量定义
const add = useSelector((state)=>state.add); const [addImgTag,setAddImgTag] = useState([]); // 页面渲染用的标签数组 const [addImgs,setAddImgs] = useState([]);
全局状态触发的初始化
当Redux全局状态add变化时,更新addImgTag:
useEffect(() => { if (add != null && add.imgArr != null) { setAddImgSize(add.imgArr.length); const tags = add.imgArr.map((item, index) => ( <div className={style.addThumb} key={"add" + index}> <img src={item.trim()} alt="광고이미지" /> <button type="button" className={style.delAddImg} onClick={(e) => { delImg(e, index); }} > x </button> <input type="hidden" name="addImg" defaultValue={item} /> </div> )); setAddImgTag(tags); },[add])
用户添加图片逻辑
用户上传图片后,生成预览标签并添加到addImgTag:
const addAddImgBox = (event)=>{ var reader = new FileReader(); reader.readAsDataURL(event.target.files[0]); setAddImgs([...addImgs,{"name":"addImgs","files":event.target.files}]); reader.onload = function(e){ let tag =<div className={style.addThumb} key={"addImg"+addImgSize}> <img src={e.target.result}/> <button type="button" className={style.delAddImg} onClick={(e)=>{delImg(e,addImgSize)}}>x</button> </div>; setAddImgTag([...addImgTag,tag]); setAddImgSize(addImgSize+1); } }
删除图片逻辑
点击删除按钮时处理:
const delImg = (e,index)=>{ console.log(addImgTag); // 最后添加的元素不在这个数组里 const tempTag = addImgTag.map((item,i)=>{ if(i==index){ return <></>; }else{ return item; } }) console.log(tempTag) setAddImgTag(tempTag) }
问题描述
执行删除操作时,控制台打印的addImgTag里没有最后添加的元素,但该元素在页面上能正常显示。已经把add设为Redux全局变量,不知道怎么解决addImgTag的状态不同步问题。
解决方案
核心问题是直接存储React元素到状态的反模式,加上异步回调中访问过时状态快照,以及删除逻辑的错误处理,按以下步骤修复:
1. 状态存数据而非React元素
React状态应该存储数据源,渲染逻辑放在JSX中,替换原addImgTag为存储图片数据的数组:
// 存储用户本地上传的图片base64数据 const [localImgs, setLocalImgs] = useState([]); // 合并全局Redux图片和本地图片,用于渲染 const allImgs = useMemo(() => { return [...(add?.imgArr || []), ...localImgs]; }, [add, localImgs]);
2. 修正添加图片的逻辑
利用setState的函数式更新获取最新状态,避免异步回调中访问旧值:
const addAddImgBox = (event)=>{ const file = event.target.files[0]; if (!file) return; const reader = new FileReader(); reader.readAsDataURL(file); // 用函数式更新获取最新的addImgs状态 setAddImgs(prev => [...prev, {"name":"addImgs","files":[file]}]); reader.onload = function(e){ // 同样用函数式更新更新本地图片数组 setLocalImgs(prev => [...prev, e.target.result]); } }
3. 修复删除逻辑
区分全局Redux图片和本地图片,分别处理删除:
const delImg = (e, index)=>{ const globalImgCount = add?.imgArr?.length || 0; // 判断要删除的是全局图片还是本地图片 if (index < globalImgCount) { // 触发Redux action删除全局图片,示例: // dispatch(deleteAddImg(index)); } else { // 计算本地图片的索引,过滤删除 const localIndex = index - globalImgCount; setLocalImgs(prev => prev.filter((_, i) => i !== localIndex)); } }
4. 动态渲染元素
在JSX中直接基于allImgs生成渲染内容,不再依赖预存的元素数组:
{allImgs.map((item, index) => ( <div className={style.addThumb} key={`img-${index}`}> <img src={item.trim()} alt="광고이미지" /> <button type="button" className={style.delAddImg} onClick={(e) => delImg(e, index)} > x </button> {/* 仅全局图片需要hidden input,本地图片提交时从addImgs中读取 */} {index < (add?.imgArr?.length || 0) && ( <input type="hidden" name="addImg" defaultValue={item} /> )} </div> ))}
5. 清理冗余状态
删除原有的addImgTag和addImgSize状态,用allImgs.length替代addImgSize的功能。
内容的提问来源于stack exchange,提问作者홍유진
相关产品推荐
相关产品推荐

