React开发:通过matchId匹配已保存预测值回填赛事比分输入框
问题原因
你现在的匹配逻辑完全依赖数组索引、Object.keys()返回的键顺序,这种方式天生不稳定——只要赛事列表排序调整、预测数据增删、对象键枚举顺序和预期不一致,就会出现回填数据错位。
你的SAVED_PREDICTIONS本身就是以赛事id为键存储的,根本不需要绕弯用索引做匹配,直接拿当前渲染赛事的id当键取值即可。
修复方案
核心修改点
- 删除PredictField组件内通过
Object.keys取键名再按innerIndex找值的逻辑,直接使用当前赛事的id作为键,从预测数据对象中取对应记录 - 补全useEffect依赖数组,解决预测数据异步从Firestore加载完成后,输入框值不更新的问题
- 增加空值容错,避免预测数据不存在时抛出JS错误
- 修复原输入框取值的隐式类型问题,避免输入值存成字符串
修改后的PredictField组件代码
import { useEffect, useState } from "react"; import { useSelector } from "react-redux"; export const PredictField = (props: any) => { const { fixture, onchange, index } = props; const predictions = useSelector((state: any) => state.predictForm); const [home, setHome] = useState(0); const [away, setAway] = useState(0); useEffect(() => { // 先判断对应比赛日的预测数据是否存在 const matchDayPredictions = predictions.userPredictions?.[0]?.[index]; if (!matchDayPredictions) { setHome(0); setAway(0); return; } // 直接用当前赛事id当键取对应预测,完全不依赖索引 const currentMatchPrediction = matchDayPredictions[fixture.id]; if (!currentMatchPrediction) { setHome(0); setAway(0); return; } // 回填比分,null/undefined值兜底为0 setHome(currentMatchPrediction.score.fullTime.homeTeam ?? 0); setAway(currentMatchPrediction.score.fullTime.awayTeam ?? 0); // 相关值变化时自动重新匹配回填 }, [fixture.id, predictions, index]); const handleOnChangeHome = (e: any) => { const value = Number(e.value) || 0; setHome(value); onchange(e); }; const handleOnChangeAway = (e: any) => { const value = Number(e.value) || 0; setAway(value); onchange(e); }; return ( <div> <p> {fixture.matchday}, {fixture.id} </p> <label>{fixture.homeTeam.name.replace("FC", "")}</label> <input name={`homeTeam-${fixture.id}`} type="number" value={home} onChange={(e) => handleOnChangeHome(e.target)} /> <input name={`awayTeam-${fixture.id}`} type="number" value={away} onChange={(e) => handleOnChangeAway(e.target)} /> <label>{fixture.awayTeam.name.replace("FC", "")}</label> </div> ); };
可选优化
Predict组件遍历赛事列表时,原来的key用的是数组索引i,建议改成赛事id当key,避免列表重排时出现组件状态复用错误,同时可以删掉没用的innerIndex传参:
{fixture.map((el: any) => ( <PredictField key={el.id} allFixtures={data} fixture={el} predictions={predictions} matchDay={el.matchday} index={index} onchange={onchange} /> ))}
通过业务唯一ID匹配关联数据的方式,不会受列表排序、数据增删的影响,稳定性远高于索引匹配。
内容的提问来源于stack exchange,提问作者artworkjpm
相关产品推荐
相关产品推荐

