我正在使用react-dom库中的useFormState构建一个表单。它的字段之一涉及我用react-dropzone实现的文件输入。我当前的代码是:
表格
export default function Form() {
const [files, setFiles] = useState<File[]>([]);
const initialState = { message: "" };
const [state, dispatch] = useFormState(sendForm, initialState);
return (
<form action={dispatch}>
<DragDrop />
<FormActions />
<Button type="submit">Send</Button>
</form>
);
}
拖放元素(文件输入)
export default function DragDrop() {
const onDrop = useCallback((droppedFiles: File[]) => {
console.log(droppedFiles);
}, []);
const { getRootProps, getInputProps } = useDropzone({
onDrop,
accept: {
"application/pdf": [".pdf"],
},
});
return (
<div {...getRootProps()}>
<p>Drop or select a file here</p>
<Button aria-disabled={false}>Select</Button>
<input {...getInputProps()} name="files" />
</div>
);
}
形成行动
export async function postFiles(prevState: State, formData: FormData) {
const files = formData.get("files");
console.log("files", files);
//implement files upload
return {
message: "Uploaded",
};
}
当我提交表单并触发 postFiles 函数时,问题就出现了。当尝试从 formData 检索“file”属性并将其分配给“files”常量时,它返回空值。该常量以 null 结尾,这表明尽管在输入元素中进行了声明,但在识别表单中的 files 属性时可能存在问题。
react-dropzone 是否会覆盖“name”属性?我有什么遗漏的吗?
谢谢!
我遇到了同样的问题,这是我想出的解决方案。
React-dropzone 仅处理拖放操作,因此拖放的文件属于
DataTransfer
对象。另一方面,通过 input[type=file]
添加的文件存储在 FormData
对象中。
两者都使用FileList接口,但它们是不同的,所以你必须自己弥补差距,并将DataTransfer对象的文件添加到
input.files
。
为了方便起见,我创建了一个
ref
到 form
:
const formRef = useRef<HTMLFormElement>(null);
在
onDrop
功能中:
const onDrop = useCallback((acceptedFiles: File[], fileRejections: FileRejection[]) => {
if (acceptedFiles.length === 1) {
// Add the file to the input[file] element (react-dropzone doesn't do it)
const dataTransfer = new DataTransfer();
dataTransfer.items.add(acceptedFiles[0]);
if (formRef.current) {
const input: HTMLInputElement | null = formRef.current.querySelector('input[type=file]');
if (input) {
input.files = dataTransfer.files;
}
}
// ...
}
}
现在,拖放的文件属于表单,可以在
FormData
中访问。
希望这有帮助!