复用数组作为表单初始值失效问题求助(含可复现示例)
解决表单初始值引用共享导致的验证异常问题
你遇到的核心问题是引用类型的浅克隆陷阱:虽然你用了slice()或者扩展运算符[...daySchema]克隆数组,但这只是做了浅克隆——数组本身是新的,但数组里的每个{ startTime: "", endTime: "" }对象还是同一个引用。这就导致所有星期几的时间段都共享同一批对象,表单状态互相干扰,最终验证逻辑出错。
解决方案:生成独立的对象结构
要彻底解决这个问题,我们需要确保每个星期几的数组和里面的对象都是全新的实例,推荐以下几种方式:
1. 使用工厂函数(最推荐)
创建一个函数,每次调用都返回全新的数组和对象,从根源避免引用共享:
// 工厂函数:每次调用都生成新的日时段结构 const createDaySlots = () => [ { startTime: "", endTime: "" }, { startTime: "", endTime: "" }, { startTime: "", endTime: "" } ]; // 初始化表单值 const initialDefaultValues = { weekdays: { monday: createDaySlots(), tuesday: createDaySlots(), wednesday: createDaySlots(), thursday: createDaySlots(), friday: createDaySlots(), saturday: createDaySlots(), sunday: createDaySlots() } };
2. 深克隆已有结构
如果已经定义了daySchema,可以用JSON.parse(JSON.stringify())做深克隆(适合纯对象/数组的场景):
const daySchema = [ { startTime: "", endTime: "" }, { startTime: "", endTime: "" }, { startTime: "", endTime: "" } ]; const initialDefaultValues = { weekdays: { monday: JSON.parse(JSON.stringify(daySchema)), tuesday: JSON.parse(JSON.stringify(daySchema)), wednesday: JSON.parse(JSON.stringify(daySchema)), // 其他星期几... } };
3. 针对两层结构的自定义克隆
如果不想用JSON序列化的方式,可以对数组里的每个对象单独克隆:
const daySchema = [ { startTime: "", endTime: "" }, { startTime: "", endTime: "" }, { startTime: "", endTime: "" } ]; // 克隆数组+里面的每个对象 const cloneDaySchema = () => daySchema.map(slot => ({ ...slot })); const initialDefaultValues = { weekdays: { monday: cloneDaySchema(), tuesday: cloneDaySchema(), wednesday: cloneDaySchema(), // 其他星期几... } };
为什么之前的方法无效?
slice()和[...daySchema]只能克隆数组的第一层,数组内的对象仍然是原引用。比如:
const arr = [{ a: 1 }]; const clonedArr = [...arr]; clonedArr[0].a = 2; console.log(arr[0].a); // 输出2,因为对象引用没变
这就是为什么你修改某一天的时段时,其他天的状态也会跟着变,最终导致表单验证无法正确触发。
用上面的方法处理后,每个星期几的时段结构都是完全独立的,表单验证就能正常工作了。
内容的提问来源于stack exchange,提问作者Remi
相关产品推荐
相关产品推荐

