Formik - обрабатывать взлом файла - почему компонент перерисовывается при выборе файла? - PullRequest
0 голосов
/ 08 января 2020

Мне хорошо известно, что formik не поддерживает загрузку файлов. Я читал, что там есть хаки. Я попробовал тот ниже с onChange, setFieldValue и event.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;

1 Ответ

1 голос
/ 15 января 2020

Я не уверен, почему вы думаете, что Formik не поддерживает файлы. Formik управляет значениями в состоянии, поэтому нет определенной c причины, по которой вы не можете использовать файлы (или любые другие типы данных), кроме того, что поле Formik по умолчанию не настроено для обработки этих объектов.

Согласно документам Formik - https://jaredpalmer.com/formik/docs/api/field

автоматически подключит входы к Formik. Он использует атрибут name, чтобы соответствовать состоянию Formik. по умолчанию будет использоваться элемент HTML.

Здесь действительно важно то, как входы подключены к Formik. В вашем случае вы устанавливаете реквизит onChange. Это переопределит «проводку» по умолчанию Formik для onChange. Другой бит «связывания» по умолчанию от formik - установить значение входного тега HTML равным значению состояния для этого поля. Отсюда ваша конкретная проблема, потому что при использовании реакции все входные данные файла должны быть неконтролируемыми (не контролируемыми состоянием).

Согласно документам реагирования - https://reactjs.org/docs/uncontrolled-components.html#the -file-input-tag

В React всегда является неуправляемым компонентом, поскольку его значение может только устанавливается пользователем, а не программно.

Поэтому, чтобы решить эту проблему, вы захотите создать обычный HTML входной тег с помощью onChange для установки значения formik по вашему желанию. Проблема с этим в том, что она неконтролируема, она не совпадает с * form39. Как мы уже знаем, мы не можем контролировать ввод файлов, поэтому нам придется использовать обходной путь. Обычно люди скрывают свой «настоящий» компонент ввода файлов и вместо этого отображают компонент-заполнитель, который отображает состояние. Наконец, «заполнитель» подключается с использованием команды Ref 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

Что еще приятно, так это то, что вы можете реально влиять на то, как выглядит этот компонент-заполнитель, так что вы можете иметь необычную кнопку ввода или что-то еще (можете рассмотреть возможность использования файловых объектов в других полях, таких как как размер - https://developer.mozilla.org/en-US/docs/Web/API/File)

...