如何解决动态生成表单组件重渲染时的焦点丢失问题
解决动态表单重渲染丢失焦点的问题
问题根源
你遇到的焦点丢失,核心是**InputSwitch内部给子组件设置的key不稳定**——你用了field对象作为key,每次字段值更新时,field对象的引用会发生变化(比如更新value时可能生成了新对象),React会把它识别成全新的组件,卸载旧组件再挂载新的,焦点自然就丢了。外层循环的key用字段名是对的,不用改。
修复方案
直接修改InputSwitch内部子组件的key,改用稳定不变的标识(比如传入的id),或者干脆去掉内部的key(因为InputSwitch本身已经在外层循环里设置了唯一key,内部子组件不需要额外加key)。
修改后的InputSwitch代码
const InputSwitch = ({ id, field }) => { if (field.type === "text") { return ( <BasicTextArea key={id} // 改用稳定的字段id作为key editable={store.editMode} sectionTitle={field.name} sectionInputId={id} inputValue={field.value} sectionInputPlaceholder={field.placeholder} onChange={updateContentFieldValue} /> ); } if (field.type === "list") { return ( <List key={id} // 同样使用稳定的id editable={store.editMode} sectionTitle={field.name} sectionInputId={id} sectionInputPlaceholder={field.placeholder} items={field.value} onChange={updateContentFieldValue} /> ); } }
额外优化建议
如果你的updateContentFieldValue方法在更新状态时是直接修改原field对象属性,建议改成不可变更新的方式,用展开运算符创建新对象,避免不必要的引用变化:
const updateContentFieldValue = (id, newValue) => { store.setState({ fields: { ...store.fields, contentFields: { ...store.fields.contentFields, [id]: { ...store.fields.contentFields[id], value: newValue } } } }); }
这种方式能保证除value外,field的其他属性和引用变化最小,进一步提升组件渲染的稳定性。
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

