高尔夫计分卡表单:动态嵌套TeeBox对象值丢失问题求助
高尔夫计分卡表单数据保留问题
问题描述
我开发了一个高尔夫计分卡表单,每个球洞的数据会被存入对象数组,每个球洞的嵌套TeeBox对象是动态的。当前遇到的问题是无法保留TeeBox[i]对象的历史值,仅最后输入的球洞值被保留。原本以为使用扩展运算符...teeBox['teeBox' + tee]可以保留历史值,但尝试多种写法后仍未解决。
相关代码
let scorecardData = [] let teeBox = {} const handleScorecard = (e, hole, holeIndex, tee) => { const { name, value } = e.target if (name === 'tees') { teeBox['teeBox' + tee] = { ...teeBox['teeBox' + tee], 'color': value } } if (name === 'yards') { teeBox['teeBox' + tee] = { ...teeBox['teeBox' + tee], 'yards': value } } if (name === 'par') { scorecardData[holeIndex] = { ...scorecardData[holeIndex], 'par': value, } } if (name === 'handicap') { scorecardData[holeIndex] = { ...scorecardData[holeIndex], 'handicap': value, 'Hole': hole } } scorecardData[holeIndex] = { ...scorecardData[holeIndex], tees: teeBox } }
<Table className={classes.scorecardTableContainer} aria-label="scorecard"> <TableBody> <TableRow> <TableCell className={classes.scorecardHolesCell}>Holes</TableCell> {[1, 2, 3, 4, 5, 6, 7, 8, 9].map((x, i) => ( <TableCell className={classes.scorecardHolesCell} key={i}> {x} </TableCell> ))} </TableRow> {[1, 2, 3].map((tee, teeIndex) => ( <TableRow key={teeIndex}> <TableCell> <TextField inputProps={{ maxLength: 10 }} id={`teeBoxInput${tee}`} name="tees" placeholder={`Tee ${tee}`} variant="outlined" onChange={(e) => handleScorecard(e, 0, 0, tee)} /> </TableCell> {[1, 2, 3, 4, 5, 6, 7, 8, 9].map((hole, holeIndex) => ( <TableCell key={holeIndex}> <TextField inputProps={{ maxLength: 3 }} id={`yardInput${hole}`} name="yards" fullWidth variant="outlined" onChange={(e) => handleScorecard(e, hole, holeIndex, tee)} /> </TableCell> ))} </TableRow> ))} <TableRow> <TableCell className={classes.scorecardParCell}>Par</TableCell> {[1, 2, 3, 4, 5, 6, 7, 8, 9].map((hole, holeIndex) => ( <TableCell key={holeIndex}> <TextField inputProps={{ maxLength: 1 }} id={`parInput${hole}`} name="par" fullWidth variant="outlined" onChange={(e) => handleScorecard(e, hole, holeIndex)} /> </TableCell> ))} </TableRow> <TableRow> <TableCell className={classes.scorecardHandicapCell}>Handicap</TableCell> {[1, 2, 3, 4, 5, 6, 7, 8, 9].map((hole, holeIndex) => ( <TableCell key={holeIndex}> <TextField inputProps={{ maxLength: 2 }} id={`handicapInput${hole}`} name="handicap" fullWidth variant="outlined" onChange={(e) => handleScorecard(e, hole, holeIndex)} /> </TableCell> ))} </TableRow> </TableBody> </Table>
尝试过的方法
直接在数组中设置值,但使用动态键时引发语法错误:Parsing error: Unexpected token, expected ","
scorecardData[holeIndex] = { ...scorecardData[holeIndex], tees: { teeBox['teeBox' + tee]: { ...teeBox['teeBox' + tee], 'color': value } } }
当前输出
球洞1(第一个对象)未保留最初输入的yards值'444'和'333',反而球洞1和球洞2都使用最后输入的yards值'321'和'301'
[ { "tees": { "teeBox1": { "color": "blue", "yards": "321" }, "teeBox2": { "color": "white", "yards": "301" } }, "par": "4", "handicap": "1", "Hole": 1 }, { "tees": { "teeBox1": { "color": "blue", "yards": "321" }, "teeBox2": { "color": "white", "yards": "301" } }, "par": "4", "handicap": "2", "Hole": 2 } ]
预期输出
球洞1(第一个对象)保留最初输入的yards值'444'和'333'
[ { "tees": { "teeBox1": { "color": "blue", "yards": "444" }, "teeBox2": { "color": "white", "yards": "333" } }, "par": "4", "handicap": "1", "Hole": 1 }, { "tees": { "teeBox1": { "color": "blue", "yards": "321" }, "teeBox2": { "color": "white", "yards": "301" } }, "par": "4", "handicap": "2", "Hole": 2 } ]
解决方案
问题根源
你使用了全局的teeBox对象,所有球洞的tees属性都引用同一个对象。当修改任意球洞的yards时,实际是修改这个全局对象的属性,导致所有球洞的tees同步变化,最终只保留最后一次修改的值。
修复后的代码
// 维护全局的tee颜色(所有球洞共享) let teeColors = {}; // 计分卡数据 let scorecardData = []; const handleScorecard = (e, hole, holeIndex, tee) => { const { name, value } = e.target; // 确保当前球洞的数据已初始化 if (!scorecardData[holeIndex]) { scorecardData[holeIndex] = { tees: {}, par: '', handicap: '', Hole: hole }; } const currentHole = scorecardData[holeIndex]; if (name === 'tees') { // 更新全局tee颜色 const teeKey = `teeBox${tee}`; teeColors[teeKey] = value; // 同步更新所有球洞的对应tee颜色 scorecardData = scorecardData.map(holeData => { return { ...holeData, tees: { ...holeData.tees, [teeKey]: { ...holeData.tees[teeKey], color: value } } }; }); } if (name === 'yards') { // 只更新当前球洞对应tee的yards,同步全局颜色 const teeKey = `teeBox${tee}`; scorecardData[holeIndex] = { ...currentHole, tees: { ...currentHole.tees, [teeKey]: { color: teeColors[teeKey] || '', yards: value } } }; } if (name === 'par') { scorecardData[holeIndex] = { ...currentHole, par: value }; } if (name === 'handicap') { scorecardData[holeIndex] = { ...currentHole, handicap: value, Hole: hole }; } };
关键说明
- 拆分全局与独立数据:用
teeColors单独存储所有球洞共享的tee颜色,每个球洞的tees对象仅存储自身的yards值,避免数据共享冲突。 - 独立维护球洞数据:每个球洞的
tees都是独立对象,修改某一球洞的yards不会影响其他球洞。 - 动态键正确写法:对象字面量中使用动态键时,需用方括号
[]包裹,比如[teeKey],这也是你之前代码报错的原因。
内容的提问来源于stack exchange,提问作者foshesco
相关产品推荐
相关产品推荐

