如何使用useReducer为状态数组中的对象添加上传进度属性
如何在useReducer中更新数组对象的上传进度属性?
嗨,看起来你已经离目标很近了!问题的核心是在useReducer里正确更新数组中特定对象的属性,同时严格遵循React状态管理的不可变性原则。我来帮你搞定这个逻辑:
第一步:修改reducer的adduploadprogress分支逻辑
我们需要通过文件对象的引用精准匹配目标项,同时返回全新的数组和对象(避免直接修改原state):
function fileSelectReducer(state, action) { switch (action.type) { case 'add': return [...state, action.filex] case 'adduploadprogress': // 用map遍历生成新数组,保证状态不可变 return state.map(item => { // 通过文件对象的引用匹配目标项 if (item.file === action.file) { // 返回新对象,合并原有属性与新的percent return { ...item, percent: action.percent } } // 非目标项直接返回原对象 return item }) case 'remove': const update = [...state] update.splice(update.indexOf(action.file), 1) document.getElementById(fileattach).value = '' return update default: return state } }
第二步:调整触发函数的参数传递
原来的触发函数把参数包装成filex会增加冗余,我们直接传递file和percent更直观:
function adduploadprogress({ file, percent }) { // 直接传递type、file和percent给reducer setfileSelectedArrax({ type: 'adduploadprogress', file, percent }) }
为什么之前的尝试没成功?
大概率是这两个原因:
- 违背了不可变性原则:如果直接修改原state数组里的对象(比如
item.percent = percent),React无法检测到状态变化,不会触发组件重渲染;而我们用map生成新数组、用{...item}创建新对象,就是为了让React能感知到状态更新。 - 匹配逻辑不准确:如果之前用文件名等内容匹配,遇到重名文件会出错;而用对象引用
item.file === action.file匹配,因为是同一个文件对象的引用,能精准定位目标项。
进阶优化:用唯一ID替代引用匹配
如果你的业务场景中文件引用可能发生变化(比如重新选择同名文件),建议在添加文件时分配唯一ID,让匹配更稳定:
- 修改
add分支,添加唯一标识:
case 'add': // 用Date.now()生成临时唯一ID,也可以用uuid库生成更规范的ID const newFileItem = { ...action.filex, id: Date.now() } return [...state, newFileItem]
- 调整触发函数,传递ID和进度:
function adduploadprogress({ id, percent }) { setfileSelectedArrax({ type: 'adduploadprogress', id, percent }) }
- 更新
adduploadprogress分支的匹配逻辑:
case 'adduploadprogress': return state.map(item => { if (item.id === action.id) { return { ...item, percent: action.percent } } return item })
这样就能稳定实现每个文件的上传进度更新啦!
内容的提问来源于stack exchange,提问作者Nick Wild
相关产品推荐
相关产品推荐

