React+TypeScript表单提交时更新localStorage对象数组的progress值
解决方案
修改步骤
1. 调整钩子解构逻辑
你已经封装了包含更新能力的useLocalStorageSkills钩子,首先需要从钩子返回值中解构出editSkill方法用于更新存储数据:
// 原来的写法 // const { skills } = useLocalStorageSkills(); // 修改为 const { skills, editSkill } = useLocalStorageSkills();
2. 优化目标技能获取逻辑
因为title是技能的唯一标识,不需要用filter返回数组,改用find直接获取单条目标技能,简化后续调用:
const { title }: { title: string } = useParams(); // 替换原来的filter逻辑 const currentSkill = skills.find(skill => skill.title === String(title)); // 可选添加边界判断,找不到对应技能时跳回首页 if (!currentSkill) { history.push('/'); return <></>; }
3. 重写表单提交逻辑
修改handleSubmit函数,计算新的进度值后同步更新到localStorage:
function handleSubmit(event: React.FormEvent) { event.preventDefault(); const hrs = parseInt(hours); const mins = parseInt(minutes); // 计算新增后的总时长,如果你要更新的是技能本身的progress属性,可直接用currentSkill.progress累加 const addedProgress = currentSkill.progress + hrs + mins * 0.015; // 构造新的技能对象,保留原有属性仅更新progress const updatedSkill = { ...currentSkill, progress: addedProgress }; // 调用editSkill同步到localStorage editSkill(currentSkill, updatedSkill); // 如果还需要保留本地的value状态可以同步更新 setValue(addedProgress); // 提交后可以重置滑块 setHours('0'); setMinutes('0'); }
4. 优化渲染逻辑
原来多处用到的filteredSkills.map可以直接替换为使用currentSkill,无需循环渲染:
// 例如原来的Header渲染 <Header {...currentSkill} key={currentSkill.title} title={currentSkill.title} type="detail" imageSrc={currentSkill.imageSrc} onClick={() => { history.push('/'); }} />
5. 优化ranking存储逻辑
你当前把ranking的读写逻辑直接写在组件顶层,会导致每次组件渲染都重复读写localStorage,建议移到handleSubmit或者useEffect中:
// 可以在进度更新后计算ranking并存储 useEffect(() => { const currentProgress = currentSkill.progress; const ranking = currentProgress === 0 ? '0' : currentProgress < 99 ? '1' : currentProgress < 199 ? '2' : currentProgress < 299 ? '3' : currentProgress < 399 ? '4' : '5'; localStorage.setItem('ranking', ranking); }, [currentSkill.progress]);
补充说明
如果你的value状态只是用来展示进度,完全可以直接读取currentSkill.progress,不需要额外维护本地状态,减少数据不一致的问题。
内容的提问来源于stack exchange,提问作者Christoph Schmitz
相关产品推荐
相关产品推荐

