Formik-处理文件hack-为什么在选择文件时重新渲染组件?

问题描述 投票:0回答:1

我很清楚,formik不支持文件上传。我读过那里有黑客。我已经用onChangesetFieldValueevent.current.target尝试了以下方法。问题在于,当选择文件时,组件将呈现,并且整个页面将变为空白。我究竟做错了什么?谢谢!

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;
reactjs file-upload formik
1个回答
0
投票

我不确定您为什么认为Formik不支持文件。 Formik在状态中管理值,因此除了未设置默认Formik字段来处理这些对象外,没有其他原因不能使用文件(或任何其他类型的数据)。

根据Formik文档-https://jaredpalmer.com/formik/docs/api/field

将自动将输入连接到Formik。它使用name属性与Formik状态进行匹配。将默认为HTML元素。

这里真正的关键是如何将输入连接到Formik。您需要设置onChange属性。这将覆盖onik的Formik的默认“接线”。 Formik的默认“接线”的另一点是将HTML输入标签的值设置为等于该字段的状态值。这是您特定问题的出处,因为在使用react时,所有文件输入都必须不受控制(不受状态控制)。

根据react docs-https://reactjs.org/docs/uncontrolled-components.html#the-file-input-tag

在React中,an始终是不受控制的组件,因为其值只能由用户设置,而不能以编程方式设置。

因此,要解决此问题,您将需要制作一个带有onChange的普通HTML输入标签,以根据需要设置formik值。这个问题是因为它不受控制,所以与formik不同步。众所周知,我们无法控制文件输入,因此我们将不得不使用变通方法。人们通常要做的是隐藏他们的“真实”文件输入组件,而是渲染一个显示状态的“占位符”组件。最后,使用react Ref连接“占位符”,以便您可以与文件输入进行交互,而无需从“占位符”呈现它。

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上查看此>

现在还不错的是,您实际上可以影响此“占位符”组件的外观,因此您可以使用精美的输入按钮或其他任何东西(可以考虑使用文件对象的其他字段,例如size-https://developer.mozilla.org/en-US/docs/Web/API/File

© www.soinside.com 2019 - 2024. All rights reserved.