gpt4 book ai didi

reactjs - react typescript : How to set multiple files to state?

转载 作者:行者123 更新时间:2023-12-05 09:08:23 26 4
gpt4 key购买 nike

我遇到了一个问题,可能是一个非常简单的问题,但我被困了几个小时,所以我想寻求你的帮助。

我有一个简单的文件输入,我想将此文件设置为稍后在提交表单时上传文件的状态。

const [inputTattoos, setInputTattoos] = useState<[{}]>();

const handleImageChange = async ({
currentTarget: input,
}: React.ChangeEvent<HTMLInputElement>) => {
if (input.files === null) return;

console.log(input.files);

setInputTattoos([{ ...input.files }]);

使用这段代码,我可以将文件写入状态,但这不是我想要将其存储在状态中的方式,因为我的状态如下所示:

enter image description here

我有一个数组,里面有一个带有对象的对象。我实际上从 input.files 得到的只是一个包含对象的数组,但我无法像在控制台上获取它那样存储这个 input.files。我尝试了很多解决方案,但这是我找到的唯一可行的方法。对于其他解决方案,我总是在 State 中得到一个空对象或 FileList(undefined),例如使用此解决方案:

const [inputTattoos, setInputTattoos] = useState<FileList>()
const handleImageChange = async ({
currentTarget: input,
}: React.ChangeEvent<HTMLInputElement>) => {
if (input.files === null) return;

console.log(input.files);

setInputTattoos(input.files);

这是怎么回事?谢谢!

最佳答案

我只存储文件对象,没有对象包装器或任何东西:

const [inputTattoos, setInputTattoos] = useState<File[]>([]);
// −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−^^^^^^−−^^
const handleImageChange = ({
currentTarget: {files},
}: React.ChangeEvent<HTMLInputElement>) => {
if (files && files.length) {
setInputTattoos(existing => [...existing, ...files]);
// −−−−−−−−−−−−−−−−−−−−−^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}
// ...
}

一些注意事项:

  1. 我已经删除了async。更改处理程序不是 async 函数,并且没有任何东西会使用 async 函数将返回的 promise 。

  2. 我已将 files 属性解构为它自己的参数,以便 TypeScript 知道它不能在守卫和状态 setter 回调之间更改。 (这也很重要,因为你不应该异步访问 React 的合成事件对象的属性,除非你调用 persist。)

  3. 我使用了状态 setter 的回调版本。这在根据现有值(在本例中为以前的内容)设置状态项时很重要。

  4. 以上依赖于 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是一个FileList,而不是一个数组,我们需要将它转换为一个数组,以便concat正确处理它.

Array.from 才推出几年,但很容易被 polyfill;如果您不想这样做,这里有一个不使用任何现代元素(箭头函数除外)的替代方法:

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>

Here's a running TypeScript version .

关于reactjs - react typescript : How to set multiple files to state?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63501087/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com