使用JavaScript map动态渲染输入框时丢失焦点问题求助
问题解决:输入框因组件重渲染丢失焦点
原代码
const HeaderField = ({ handleHeaderChange, removeHeader, index, header, }: any) => ( <HeaderContainer> <TextField label="Key" value={header.key} onChange={e => handleHeaderChange(e.target.value, 'key', index)} /> <TextField label="Value" value={header.value} onChange={e => handleHeaderChange(e.target.value, 'value', index)} /> </HeaderContainer> ); const CustomHeadersField = ({ handleChange, fieldKey, categoryKey }: any) => { const [headers, setHeaders] = React.useState<headersType[] | null>(null); const addHeader = () => { const newHeaders = headers ? [...headers] : []; newHeaders.push({ key: '', value: '' }); setHeaders(newHeaders); }; const handleHeaderChange = ( value: string, type: 'key' | 'value', index: number, ) => { const newHeaders: any = headers ? [...headers] : []; if (type === 'key') { newHeaders[index].key = value; } else { newHeaders[index].value = value; } setHeaders(newHeaders); handleChange(newHeaders, fieldKey, categoryKey); }; return ( <CustomHeadersContainer> {headers?.map((header, index) => ( <HeaderField key={Math.random()} handleHeaderChange={handleHeaderChange} removeHeader={removeHeader} index={index} header={header} /> ))} <Button onClick={addHeader} variant="contained" sx={{ width: 'fit-content' }} > Add Header </Button> </CustomHeadersContainer> ); };
功能与问题
点击Add Header按钮会向headers状态中添加新的键值对,在表单中新增两个输入字段。但当前存在问题:每次在输入框按键时,header.map会销毁旧组件并重新渲染新组件,导致输入框丢失焦点。已尝试将HeaderField组件移出CustomHeadersField,但无效。
问题根源
你给HeaderField组件设置的key是Math.random(),这个值每次渲染都会生成新的随机数。React依赖key识别列表中组件的身份,当key变化时,React会认为这是全新组件,从而销毁旧组件并创建新组件,直接导致输入框失去焦点。
另外,用数组index作为key也存在隐患——如果后续有删除、排序等操作,数组元素的index会发生变化,同样会触发不必要的组件销毁重建。
解决方法
给每个header对象添加唯一标识(比如自增ID、时间戳+随机数)作为key,确保每个组件的key在生命周期内保持稳定。
修改步骤:
- 更新addHeader方法:添加新header时生成唯一id
const addHeader = () => { const newHeaders = headers ? [...headers] : []; // 用时间戳+随机数生成唯一id,也可以用uuid库实现更严谨的唯一标识 newHeaders.push({ id: `${Date.now()}-${Math.random()}`, key: '', value: '' }); setHeaders(newHeaders); };
- 修改map时的key值:使用header的id作为组件key
{headers?.map((header, index) => ( <HeaderField key={header.id} handleHeaderChange={handleHeaderChange} removeHeader={removeHeader} index={index} header={header} /> ))}
- (可选)优化handleHeaderChange:保持状态不可变性,避免直接修改数组元素
const handleHeaderChange = ( value: string, type: 'key' | 'value', index: number, ) => { const newHeaders = headers ? headers.map((item, idx) => { if (idx === index) { return { ...item, [type]: value }; } return item; }) : []; setHeaders(newHeaders); handleChange(newHeaders, fieldKey, categoryKey); };
这样修改后,每个HeaderField组件的key保持稳定,React不会随意销毁重建组件,输入框也就不会丢失焦点了。
内容的提问来源于stack exchange,提问作者Sanket hn
相关产品推荐
相关产品推荐

