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

使用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在生命周期内保持稳定。

修改步骤:

  1. 更新addHeader方法:添加新header时生成唯一id
const addHeader = () => {
  const newHeaders = headers ? [...headers] : [];
  // 用时间戳+随机数生成唯一id,也可以用uuid库实现更严谨的唯一标识
  newHeaders.push({ id: `${Date.now()}-${Math.random()}`, key: '', value: '' });
  setHeaders(newHeaders);
};
  1. 修改map时的key值:使用header的id作为组件key
{headers?.map((header, index) => (
  <HeaderField 
    key={header.id} 
    handleHeaderChange={handleHeaderChange} 
    removeHeader={removeHeader} 
    index={index} 
    header={header} 
  />
))}
  1. (可选)优化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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 14:10:20