React动态添加输入框后所有项值同步问题如何解决
解决动态添加表单字段值同步问题
问题根源
你遇到的所有变体字段值同步变化的问题,核心原因是每次添加新字段时,你直接复用了同一个AddProductVariationInitialValue对象的引用。当多个变体项共享同一个对象实例时,修改其中任意一个的属性,所有关联的项都会同步更新。
解决方案
要让每个变体字段拥有独立的值,需要保证每次添加的新字段都是一个全新的对象实例,而不是复用同一个引用。同时优化状态更新逻辑,确保修改单个字段时不会影响其他项。
步骤1:创建初始值的深拷贝
修改addVariationFields函数,每次添加新字段时,对初始值对象进行深拷贝:
const addVariationFields = () => { // 使用structuredClone深拷贝,支持复杂对象(嵌套结构) const newField = structuredClone(AddProductVariationInitialValue); // 如果是简单平面对象,也可以用扩展运算符: // const newField = {...AddProductVariationInitialValue}; setInputVariationFields(prev => [...prev, newField]); }
步骤2:优化状态更新逻辑
在BaseInput的onChange事件中,使用函数式更新获取最新状态,并复制当前对象后再修改属性,避免直接修改原状态对象:
<BaseInput key={`name_1_${index}`} id={`${index}`} name={`name_1_${index}`} type='text' value={element.name_1 || ''} onChange={(e) => { setInputVariationFields(prevFields => { // 复制数组和当前索引的对象 const updatedFields = [...prevFields]; updatedFields[index] = { ...updatedFields[index], name_1: e.target.value }; return updatedFields; }); }} placeholder='Product variation name 1' />
注意:你原来的代码里BaseInput重复写了两次value属性,需要删除其中一个。
修正后的完整核心代码
const [inputVariationFields, setInputVariationFields] = useState<AddProductVariationForm[]>([]) const addVariationFields = () => { const newField = structuredClone(AddProductVariationInitialValue); setInputVariationFields(prev => [...prev, newField]); } const removeVariationFields = (i: number) => { setInputVariationFields(prev => prev.filter((_, idx) => idx !== i)); } // 渲染部分 return ( <> {inputVariationFields.map((element, index) => ( <div className="my-3 p-3 border border-gray-lighter rounded" key={index}> <div className='w-full'> <label htmlFor={`name_1_${index}`} className='font'> Variation Name 1 <BaseInput key={`name_1_${index}`} id={`${index}`} name={`name_1_${index}`} type='text' value={element.name_1 || ''} onChange={(e) => { setInputVariationFields(prevFields => { const updatedFields = [...prevFields]; updatedFields[index] = { ...updatedFields[index], name_1: e.target.value }; return updatedFields; }); }} placeholder='Product variation name 1' /> </label> </div> {/* 其他表单字段... */} {index !== 0 && ( <div className='mt-5 mb-2'> <OutlinedButton onClick={() => removeVariationFields(index)}> Remove </OutlinedButton> </div> )} </div> ))} <div className="my-3"> <PrimaryButton type='button' onClick={addVariationFields} > Add variation </PrimaryButton> </div> </> );
额外说明
- 如果
AddProductVariationInitialValue是包含嵌套对象的复杂结构,必须使用structuredClone或者第三方库(如Lodash的cloneDeep)进行深拷贝;如果是简单平面对象,用扩展运算符{...obj}即可。 - 使用函数式更新(
setState(prev => ...))可以避免因状态异步更新导致的旧值覆盖问题,让状态更新更可靠。
内容的提问来源于stack exchange,提问作者Maaschtj Djeevta
相关产品推荐
相关产品推荐

