Formik - handle file hack - 为什么组件在选择文件时重新呈现?
Formik - handle file hack - why component re-renders when file is selected?
我很清楚formik不支持文件上传。我读到那里有黑客。我用 onChange
、setFieldValue
和 event.current.target
尝试了下面的那个。 The problem is that when file is selected, the component renders and the full page goes blank.我究竟做错了什么?谢谢!
import React from 'react';
import { Formik, Form, Field } from 'formik';
const initialValues = {
file: ''
};
const TestArt = () => {
const onSubmitFile = values => {
debugger;
};
return (
<div>
<Formik
initialValues={initialValues}
onSubmit={onSubmitFile}
component={UploadFile}
/>
</div>
);
};
function UploadFile({ setFieldValue }) {
debugger;
return (
<div>
<Form>
<Field
id="file"
type="file"
name="file"
onChange={event => {
setFieldValue('file', event.currentTarget.files[0]);
}}
/>
<button>submit</button>
</Form>
</div>
);
}
export default TestArt;
我不确定您为什么认为 Formik 不支持文件。 Formik 管理状态中的值,因此除了默认的 Formik 字段未设置为处理这些对象之外,没有特定原因不能使用文件(或任何其他类型的数据)。
根据 Formik 文档 - https://jaredpalmer.com/formik/docs/api/field
will automagically hook up inputs to Formik. It uses the name attribute to match up with Formik state. will default to an HTML element.
这里真正关键的是如何将输入连接到 Formik。在您的情况下,您正在设置 onChange 道具。这将覆盖 Formik 的默认值 "wiring" for onChange。 formik 的默认 "wiring" 的另一位是将 HTML 输入标签的值设置为等于该字段的状态值。这是您的特定问题的来源,因为在使用 React 时,所有文件输入都必须不受控制(不受状态控制)。
根据反应文档 - https://reactjs.org/docs/uncontrolled-components.html#the-file-input-tag
In React, an is always an uncontrolled component because its value can only be set by a user, and not programmatically.
因此,要解决此问题,您需要制作一个普通的 HTML 输入标签,并根据需要使用 onChange 连接来设置 formik 值。这个问题是因为它不受控制,它与 formik 不同步。正如我们所知,我们无法控制文件输入,因此我们将不得不使用变通方法。人们通常做的是隐藏他们的 "real" 文件输入组件,而是渲染一个显示状态的 "placeholder" 组件。最后 "placeholder" 使用 react Ref 连接起来,这样您就可以与文件输入交互,而无需从 "placeholder".
渲染它
import React from "react";
import { Formik, Form } from "formik";
const initialValues = {
file: ""
};
const TestArt = () => {
const onSubmitFile = values => {
debugger;
};
return (
<div>
<Formik
initialValues={initialValues}
onSubmit={onSubmitFile}
component={UploadFile}
/>
</div>
);
};
function UploadFile({ values, setFieldValue }) {
debugger;
const fileInput = React.createRef();
return (
<div>
<Form>
<input
type="file"
style={{display: "none"}}
onChange={event => {
setFieldValue("file", event.currentTarget.files[0]);
}}
ref={fileInput}
/>
<button type="button" onClick={() => fileInput.current.click()}>
Choose file
</button>
<small>
{values.file ? values.file.name || "Error" : "No file chosen"}
</small>
<br />
<button>submit</button>
</Form>
</div>
);
}
export default TestArt;
您也可以在 codesandbox 上查看此内容 - https://codesandbox.io/s/formik-file-upload-example-39orl
现在还不错的是,您实际上可以影响此 "placeholder" 组件的外观,因此您可以拥有精美的输入按钮或其他任何东西(可以考虑使用文件对象的其他字段,例如大小 - https://developer.mozilla.org/en-US/docs/Web/API/File)
我很清楚formik不支持文件上传。我读到那里有黑客。我用 onChange
、setFieldValue
和 event.current.target
尝试了下面的那个。 The problem is that when file is selected, the component renders and the full page goes blank.我究竟做错了什么?谢谢!
import React from 'react';
import { Formik, Form, Field } from 'formik';
const initialValues = {
file: ''
};
const TestArt = () => {
const onSubmitFile = values => {
debugger;
};
return (
<div>
<Formik
initialValues={initialValues}
onSubmit={onSubmitFile}
component={UploadFile}
/>
</div>
);
};
function UploadFile({ setFieldValue }) {
debugger;
return (
<div>
<Form>
<Field
id="file"
type="file"
name="file"
onChange={event => {
setFieldValue('file', event.currentTarget.files[0]);
}}
/>
<button>submit</button>
</Form>
</div>
);
}
export default TestArt;
我不确定您为什么认为 Formik 不支持文件。 Formik 管理状态中的值,因此除了默认的 Formik 字段未设置为处理这些对象之外,没有特定原因不能使用文件(或任何其他类型的数据)。
根据 Formik 文档 - https://jaredpalmer.com/formik/docs/api/field
will automagically hook up inputs to Formik. It uses the name attribute to match up with Formik state. will default to an HTML element.
这里真正关键的是如何将输入连接到 Formik。在您的情况下,您正在设置 onChange 道具。这将覆盖 Formik 的默认值 "wiring" for onChange。 formik 的默认 "wiring" 的另一位是将 HTML 输入标签的值设置为等于该字段的状态值。这是您的特定问题的来源,因为在使用 React 时,所有文件输入都必须不受控制(不受状态控制)。
根据反应文档 - https://reactjs.org/docs/uncontrolled-components.html#the-file-input-tag
In React, an is always an uncontrolled component because its value can only be set by a user, and not programmatically.
因此,要解决此问题,您需要制作一个普通的 HTML 输入标签,并根据需要使用 onChange 连接来设置 formik 值。这个问题是因为它不受控制,它与 formik 不同步。正如我们所知,我们无法控制文件输入,因此我们将不得不使用变通方法。人们通常做的是隐藏他们的 "real" 文件输入组件,而是渲染一个显示状态的 "placeholder" 组件。最后 "placeholder" 使用 react Ref 连接起来,这样您就可以与文件输入交互,而无需从 "placeholder".
渲染它import React from "react";
import { Formik, Form } from "formik";
const initialValues = {
file: ""
};
const TestArt = () => {
const onSubmitFile = values => {
debugger;
};
return (
<div>
<Formik
initialValues={initialValues}
onSubmit={onSubmitFile}
component={UploadFile}
/>
</div>
);
};
function UploadFile({ values, setFieldValue }) {
debugger;
const fileInput = React.createRef();
return (
<div>
<Form>
<input
type="file"
style={{display: "none"}}
onChange={event => {
setFieldValue("file", event.currentTarget.files[0]);
}}
ref={fileInput}
/>
<button type="button" onClick={() => fileInput.current.click()}>
Choose file
</button>
<small>
{values.file ? values.file.name || "Error" : "No file chosen"}
</small>
<br />
<button>submit</button>
</Form>
</div>
);
}
export default TestArt;
您也可以在 codesandbox 上查看此内容 - https://codesandbox.io/s/formik-file-upload-example-39orl
现在还不错的是,您实际上可以影响此 "placeholder" 组件的外观,因此您可以拥有精美的输入按钮或其他任何东西(可以考虑使用文件对象的其他字段,例如大小 - https://developer.mozilla.org/en-US/docs/Web/API/File)