当使用 javascript map 方法动态呈现输入时,输入会失去焦点

Input loses focus when javascript map method is used to render it dynamically

提问人:Sanket hn 提问时间:12/27/2022 更新时间:12/27/2022 访问量:49

问:

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)}
    />
);

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>
  );
};

“添加标题”按钮将新的键值对添加到标头状态,并在表单中添加两个新字段。

现在,header.map 会破坏旧组件,并在每次按下键时呈现新组件,从而导致其失去焦点。

我尝试将 HeaderField 组件移出 CustomHeadersField。它没有用。

感谢您的帮助!

javascript reactjs 失焦

评论


答:

1赞 JaswanthSriram 12/27/2022 #1

根据 react 文档

密钥应该是稳定、可预测和唯一的。不稳定的键(如 Math.random() 生成的键)将导致许多组件实例和 DOM 节点被不必要地重新创建,这可能会导致性能下降和子组件中的状态丢失。

将 Math.random() 作为键传递是问题所在。如果不对列表重新排序,则可以使用索引作为键。参考这个答案