我只会存储文件对象,没有对象包装器或任何东西:
const [inputTattoos, setInputTattoos] = useState<File[]>([]);
// −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−^^^^^^−−^^
const handleImageChange = ({
currentTarget: {files},
}: React.ChangeEvent<HTMLInputElement>) => {
if (files && files.length) {
setInputTattoos(existing => [...existing, ...files]);
// −−−−−−−−−−−−−−−−−−−−−^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}
// ...
}
对此有几点说明:
我已经删除了async
。更改处理程序不是async
函数,并且不会使用async
函数返回的承诺。
我已经将files
属性解构为它自己的参数,以便 TypeScript 知道它不能在警卫和状态设置器回调之间更改。(这也很重要,因为你不应该从 React 的合成事件对象中异步访问属性,除非你调用persist
.)
我使用了状态设置器的回调版本。在根据其现有值(在本例中为先前的内容)设置状态项时,这一点很重要。
以上依赖于files
(来自输入)是可迭代的,它在现代浏览器中是可迭代的,但在一些稍旧的浏览器中却不是。
关于#4,如果您需要为稍旧的浏览器解决这个问题:
const [inputTattoos, setInputTattoos] = useState<File[]>([]);
const handleImageChange = ({
currentTarget: {files},
}: React.ChangeEvent<HTMLInputElement>) => {
if (files && files.length) {
setInputTattoos(existing => existing.concat(Array.from(files))); // *** Only change is here
}
// ...
}
那里的变化是回调:
existing => existing.concat(Array.from(files))
请注意,由于files
是 a FileList
,而不是数组,因此我们需要将其转换为数组concat
以正确处理它。
Array.from
才几岁,但很容易填充;如果您不想这样做,这里有一个不使用任何现代(箭头功能除外)的替代方法:
existing => existing.concat(Array.prototype.slice.call(files))
Array.from
这是用于该部分的完整示例:
const { useState } = React;
function Example() {
const [inputTattoos, setInputTattoos] = useState/*<File[]>*/([]);
const [inputKey, setInputKey] = useState(0);
const handleImageChange = ({
currentTarget: {file},
}/*: React.ChangeEvent<HTMLInputElement>*/) => {
if (files && files.length) {
setInputTattoos(existing => existing.concat(Array.from(files)));
}
// Reset the input by forcing a new one
setInputKey(key => key + 1);
}
return (
<form>
Selected tattoos ({inputTattoos.length}):
<ul>
{inputTattoos.map((file, index) =>
<li key={index}>{file.name}</li>
)}
</ul>
Add: <input key={inputKey} type="file" onChange={handleImageChange} />
</form>
);
}
ReactDOM.render(<Example/>, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.0/umd/react-dom.production.min.js"></script>
这是一个正在运行的 TypeScript 版本。