2

我有一个自定义文件上传字段,一旦您选择/删除文件,就会立即上传文件,并返回一个 UUID 以供以后提交。所以,当你删除一个文件时,基本上现在大多数 web 应用程序(例如 Facebook、Twitter 等)都会这样做。

使用 final-form 处理这一切都很容易 -onChange一旦上传完成,我的字段只需调用 final-form 的函数以将 UUID 传递给 final-form。

但是,如果用户在上传仍在运行时提交表单,他们将提交没有文件 UUID 的表单,因为就最终表单而言,尚未选择任何文件。特别是对于较大的文件,这将是一个问题,因为用户可能没有意识到他们仍然需要等待(即使有加载指示器)。将字段标记为必填也不是一种选择,因为根本不提供文件是有效的(或者该字段可能允许多个文件,或者您正在替换以前上传的文件) - 所以该字段是“无效的”的唯一情况" 是当前正在上传文件的时间。

这是一个带有小型虚拟应用程序的代码框,应该为任何尝试解决它提供一个很好的起点:https ://codesandbox.io/s/poliished-fast-k80t7

这个想法是该字段在单击“假装开始上传”时变为无效,并在单击“假装完成上传”后再次有效。

请注意,我正在寻找一种干净的方法来做到这一点,同时保持事物分开,即我不想为此添加状态到包含Form- 的组件中,也因为验证函数需要是幂等的,所以检查外部状态会有很多破损(正如我尝试做的那样)。


如果代码和框链接中断,这里是第一个链接的相关代码(因为另一个只是一个损坏的尝试):

import React, { useState } from "react";
import { render } from "react-dom";
import Styles from "./Styles";
import { Form, Field } from "react-final-form";

const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));

const onSubmit = async values => {
  await sleep(300);
  window.alert(JSON.stringify(values, 0, 2));
};

const MyFileUploader = ({ input: { value, onChange }, meta: { invalid } }) => {
  const [isUploading, setUploading] = useState(false);
  const handleStartClick = () => {
    setUploading(true);
  };
  const handleFinishClick = () => {
    setUploading(false);
    onChange("0xdeadbeef"); // let's pretend this is the file UUID ;)
  };
  const style = { color: invalid ? "#f00" : "#000" };
  if (value) {
    return <em style={style}>{value}</em>;
  } else if (isUploading) {
    return (
      <button type="button" onClick={handleFinishClick} style={style}>
        Pretend to finish uploading
      </button>
    );
  } else {
    return (
      <button type="button" onClick={handleStartClick} style={style}>
        Pretend to start uploading
      </button>
    );
  }
};

const App = () => (
  <Styles>
    <h1>React Final Form</h1>
    <Form
      onSubmit={onSubmit}
      initialValues={{ file: null }}
      render={({ handleSubmit, form, submitting, values }) => (
        <form onSubmit={handleSubmit}>
          <div>
            <label>File</label>
            <Field name="file" component={MyFileUploader} />
          </div>
          <div className="buttons">
            <button type="submit" disabled={submitting}>
              Submit
            </button>
            <button type="button" onClick={form.reset} disabled={submitting}>
              Reset
            </button>
          </div>
          <pre>{JSON.stringify(values, 0, 2)}</pre>
        </form>
      )}
    />
  </Styles>
);

render(<App />, document.getElementById("root"));
4

1 回答 1

2

有趣的问题。

这样的事情怎么样?当文件上传时,它会呈现一个始终无效的字段,从而阻止提交。

const SubmitBlocker = ({ children }) => (
  <Field name="uploading" validate={() => children}>
    {({ meta }) =>
      meta.touched && meta.error ? meta.error : null
    }
  </Field>
);

编辑 beautiful-monad-84nu0

于 2020-01-10T14:31:59.540 回答