使用 Formik 和 React 正确处理多个文件输入
Properly handle multiple files input with Formik and React
我找不到使用 Formik 和 React 处理多个文件输入的正确方法。
import { Formik, Field } from "formik";
const MyForm = () => {
const handleOnSubmit = (actions) => {
actions.setFieldValue("files", "");
};
return (
<Formik initialValues={{ files: "" }} onSubmit={handleOnSubmit}>
{({ values, handleSubmit }) => (
<form onSubmit={handleSubmit}>
<Field
id="files"
name="files"
type="file"
multiple
value={values.files}
onChange={(event) => {
setFieldValue("files", Array.from(event.target.files));
}}
/>
<button type="submit">Submit</button>
</form>
)}
</Formik>
);
};
如果你通过 value={values.files}
你会得到 InvalidStateError
:
Failed to set the 'value' property on 'HTMLInputElement': This input element accepts a filename, which may only be programmatically set to the empty string.
如果您通过 value={values.files ? undefined : ""}
有效但您收到 React 警告:
A component is changing an uncontrolled input to be controlled.
如果您通过 value={undefined}
,您将无法控制输入值(用于在提交表单时清空文件 selection)。
并且如果你传递 value=""
你在 selecting 文件时不会得到 selected 文件的名称(或 select 文件的数量)在输入上。
我错过了什么吗?谢谢。
在 Codesandbox.io 查看示例。
我设法通过将 files
设置为 event.currentTarget.files
并使用 <input/>
而不是 Formik 的 <Field/>
.
让您的示例正常工作
import { Formik } from "formik";
export default function App() {
return (
<div className="App">
<Formik
initialValues={{ files: null }}
onSubmit={(values) => {
console.log(values);
}}
>
{({ setFieldValue, handleSubmit }) => (
<form onSubmit={handleSubmit}>
<input
name="files"
type="file"
multiple
onChange={(event) => {
setFieldValue("files", event.currentTarget.files);
}}
/>
<button type="submit">Submit</button>
</form>
)}
</Formik>
</div>
);
}
您可以签出沙盒 here。
您可以使用 useRef
获取对文件输入的引用并像这样清除它。
import { Formik, Field } from "formik";
import { useRef } from "react";
export default function App() {
const fileRef = useRef();
return (
<div className="App">
<Formik
initialValues={{ files: null }}
onSubmit={console.log}
>
{({ setFieldValue, handleSubmit }) => (
<form onSubmit={handleSubmit}>
<Field
innerRef={fileRef}
name="files"
type="file"
multiple
/>
<button type="submit">Submit</button>
</form>
)}
</Formik>
<button onClick={() => (fileRef.current.value = null)}>Clear</button>
</div>
);
}
我找不到使用 Formik 和 React 处理多个文件输入的正确方法。
import { Formik, Field } from "formik";
const MyForm = () => {
const handleOnSubmit = (actions) => {
actions.setFieldValue("files", "");
};
return (
<Formik initialValues={{ files: "" }} onSubmit={handleOnSubmit}>
{({ values, handleSubmit }) => (
<form onSubmit={handleSubmit}>
<Field
id="files"
name="files"
type="file"
multiple
value={values.files}
onChange={(event) => {
setFieldValue("files", Array.from(event.target.files));
}}
/>
<button type="submit">Submit</button>
</form>
)}
</Formik>
);
};
如果你通过 value={values.files}
你会得到 InvalidStateError
:
Failed to set the 'value' property on 'HTMLInputElement': This input element accepts a filename, which may only be programmatically set to the empty string.
如果您通过 value={values.files ? undefined : ""}
有效但您收到 React 警告:
A component is changing an uncontrolled input to be controlled.
如果您通过 value={undefined}
,您将无法控制输入值(用于在提交表单时清空文件 selection)。
并且如果你传递 value=""
你在 selecting 文件时不会得到 selected 文件的名称(或 select 文件的数量)在输入上。
我错过了什么吗?谢谢。
在 Codesandbox.io 查看示例。
我设法通过将 files
设置为 event.currentTarget.files
并使用 <input/>
而不是 Formik 的 <Field/>
.
import { Formik } from "formik";
export default function App() {
return (
<div className="App">
<Formik
initialValues={{ files: null }}
onSubmit={(values) => {
console.log(values);
}}
>
{({ setFieldValue, handleSubmit }) => (
<form onSubmit={handleSubmit}>
<input
name="files"
type="file"
multiple
onChange={(event) => {
setFieldValue("files", event.currentTarget.files);
}}
/>
<button type="submit">Submit</button>
</form>
)}
</Formik>
</div>
);
}
您可以签出沙盒 here。
您可以使用 useRef
获取对文件输入的引用并像这样清除它。
import { Formik, Field } from "formik";
import { useRef } from "react";
export default function App() {
const fileRef = useRef();
return (
<div className="App">
<Formik
initialValues={{ files: null }}
onSubmit={console.log}
>
{({ setFieldValue, handleSubmit }) => (
<form onSubmit={handleSubmit}>
<Field
innerRef={fileRef}
name="files"
type="file"
multiple
/>
<button type="submit">Submit</button>
</form>
)}
</Formik>
<button onClick={() => (fileRef.current.value = null)}>Clear</button>
</div>
);
}