wyn*_*007 2 typescript reactjs typescript-typings react-hooks
我面临一个问题,可能是一个非常简单的问题,但我被困了几个小时,所以我想请求你的帮助。
我有一个简单的文件输入,我想将此文件设置为稍后在提交表单时上传文件。
const [inputTattoos, setInputTattoos] = useState<[{}]>();
const handleImageChange = async ({
currentTarget: input,
}: React.ChangeEvent<HTMLInputElement>) => {
if (input.files === null) return;
console.log(input.files);
setInputTattoos([{ ...input.files }]);
Run Code Online (Sandbox Code Playgroud)
使用这段代码,我可以将文件写入状态,但这不是我想要将其存储在状态中的方式,因为我的状态如下所示:
我有一个数组,里面有一个带有对象的对象。我实际上从 input.files 得到的只是一个包含对象的数组,但我无法像在控制台上获取它一样存储此 input.files 。我尝试了很多解决方案,但这是我发现唯一有效的方法。使用其他解决方案时,我总是在 State 中得到一个空对象或 FileList(未定义),例如使用以下解决方案:
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);
Run Code Online (Sandbox Code Playgroud)
这是怎么回事?谢谢你!
我只会存储文件对象,没有对象包装器或任何东西:
\nconst [inputTattoos, setInputTattoos] = useState<File[]>([]);\n// \xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92^^^^^^\xe2\x88\x92\xe2\x88\x92^^\nconst handleImageChange = ({\n currentTarget: {files},\n}: React.ChangeEvent<HTMLInputElement>) => {\n if (files && files.length) {\n setInputTattoos(existing => [...existing, ...files]);\n// \xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n }\n // ...\n}\nRun Code Online (Sandbox Code Playgroud)\n对此有几点说明:
\n我已经删除了async. 更改处理程序不是async函数,并且没有任何内容会使用函数async将返回的承诺。
我已将files属性解构为它自己的参数,以便 TypeScript 知道它无法在防护和状态设置器回调之间进行更改。(这也很重要,因为除非您调用,否则您不应该异步访问 React 的合成事件对象的属性persist。)
我使用了状态设置器的回调版本。当根据状态项的现有值(在本例中为先前的内容)设置状态项时,这一点很重要。
\n上面的内容依赖于files(来自输入)可迭代,这在现代浏览器中是可迭代的,但在一些稍旧的浏览器中却不是。
关于#4,如果您需要为稍旧的浏览器解决这个问题:
\nconst [inputTattoos, setInputTattoos] = useState<File[]>([]);\nconst handleImageChange = ({\n currentTarget: {files},\n}: React.ChangeEvent<HTMLInputElement>) => {\n if (files && files.length) {\n setInputTattoos(existing => existing.concat(Array.from(files))); // *** Only change is here\n }\n // ...\n}\nRun Code Online (Sandbox Code Playgroud)\n那里的变化是回调:
\nexisting => existing.concat(Array.from(files))\nRun Code Online (Sandbox Code Playgroud)\n请注意,由于files是FileList,而不是数组,因此我们需要将其转换为数组才能concat正确处理它。
Array.from虽然只有几年的历史,但很容易进行多填充;如果您不想这样做,这里有一个不使用任何现代内容的替代方案(除了箭头函数):
existing => existing.concat(Array.prototype.slice.call(files))\nRun Code Online (Sandbox Code Playgroud)\n这是用于Array.from该部分的完整示例:
const [inputTattoos, setInputTattoos] = useState<File[]>([]);\n// \xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92^^^^^^\xe2\x88\x92\xe2\x88\x92^^\nconst handleImageChange = ({\n currentTarget: {files},\n}: React.ChangeEvent<HTMLInputElement>) => {\n if (files && files.length) {\n setInputTattoos(existing => [...existing, ...files]);\n// \xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n }\n // ...\n}\nRun Code Online (Sandbox Code Playgroud)\r\nconst [inputTattoos, setInputTattoos] = useState<File[]>([]);\nconst handleImageChange = ({\n currentTarget: {files},\n}: React.ChangeEvent<HTMLInputElement>) => {\n if (files && files.length) {\n setInputTattoos(existing => existing.concat(Array.from(files))); // *** Only change is here\n }\n // ...\n}\nRun Code Online (Sandbox Code Playgroud)\r\n| 归档时间: |
|
| 查看次数: |
9394 次 |
| 最近记录: |