You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

高尔夫计分卡表单:动态嵌套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
        };
    }
};

关键说明

  1. 拆分全局与独立数据:用teeColors单独存储所有球洞共享的tee颜色,每个球洞的tees对象仅存储自身的yards值,避免数据共享冲突。
  2. 独立维护球洞数据:每个球洞的tees都是独立对象,修改某一球洞的yards不会影响其他球洞。
  3. 动态键正确写法:对象字面量中使用动态键时,需用方括号[]包裹,比如[teeKey],这也是你之前代码报错的原因。

内容的提问来源于stack exchange,提问作者foshesco

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 22:09:58