开发者问题收集

如何修复无法在“HTMLInputElement”上设置“value”属性以进行反应?

2020-02-24
36472

我正在使用 Nextjs 并尝试上传单个文件。每次我附加新文件时,控制台日志中都会出现此错误。

在控制台中,我看到此错误:

Warning: A component is changing an uncontrolled input of type file to be controlled. Input elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component.

然后,第二个是:

react-dom.development.js:2592 Uncaught DOMException: Failed to set the 'value' property on 'HTMLInputElement': This input element accepts a filename, which may only be programmatically set to the empty string.

这是我的示例代码:

  1. 渲染函数中的 HTML 路径
<div className="form-group">
  <label htmlFor="p_file">Image</label>
  <input
    id="p_file"
    type="file"
    className="form-control-file"
    value={formData.image}
    onChange={ e => onChangeImage(e)} />
</div>
  1. Javascript 路径
const [formData, setFormData] = useState({
  ...,
  image: undefined
});

const onChangeImage = event => {
  console.log(event.target.files[0]);
  setFormData( prev => ({
    ...prev,
    image: event.target.files[0]
  }));
}
2个回答

来自 React 文档 中有关不受控制元素的内容:

In React, an <input type="file" /> is always an uncontrolled component because its value can only be set by a user, and not programmatically.

这是一项安全功能,可确保您无法在未经用户明确选择的情况下从用户磁盘提取数据。

在我看来,这似乎不是您想要做的。您要做的就是显示所选文件的名称。您可以通过创建自己的标签和按钮以及隐藏的文件元素来实现这一点。单击自定义按钮时,在 HTMLFileInput 上强制调用单击事件。在文件输入上注册您的更改事件,并使用响应更新您的自定义元素。

James Hay
2020-02-24

如果您希望每次选择文件时触发 onChange 事件(无论是同一个文件还是不同的文件),您可以在输入中设置 value={''}。每次呈现时,这将清空输入。

我从 chrisv 的这里获得了这个答案的灵感:

使用空字符串对受控组件输入值进行反应

请参阅以下示例:

import * as React from "react";
import {useEffect, useState} from "react";

const FileComponentTest = () => {
  const [file, setFile] = useState(null);

  useEffect(() => {
    console.log("File has been set.")
  },[file]);

  return (
    <React.Fragment>
      <input
        type="file"
        onChange= {(e) => setFile(e.target.files[0])}
        value ={""}
      />
    </React.Fragment>
  )
};

我在控制台中没有收到任何错误。

更新:

请参阅下面的小提琴链接:

https://jsfiddle.net/geoj12/tjbvpyzs/11/

Mr. J
2022-03-24