文件上传开始/结束时显示/隐藏微调器

时间:2018-05-09 16:38:27

标签: javascript reactjs

我正在使用this React component将文件上传到浏览器(而不是服务器)。该组件是react-jsonschema-form库的一部分,因此我无法更改源代码。此组件的render方法如下所示

  render() {
    const { multiple, id, readonly, disabled, autofocus } = this.props;
    const { filesInfo } = this.state;
    return (
      <div>
        <p>
          <input
            ref={ref => (this.inputRef = ref)}
            id={id}
            type="file"
            disabled={readonly || disabled}
            onChange={this.onChange}
            defaultValue=""
            autoFocus={autofocus}
            multiple={multiple}
          />
        </p>
        <FilesInfo filesInfo={filesInfo} />
      </div>
    );
  }

此组件接受一个或多个文件作为输入,base64对它们进行编码,并将编码文件存储在内存中。

但是,如果用户选择大文件(例如5MB),则处理时会有明显的延迟。我希望在处理开始时显示一个微调器并在完成时隐藏它,但我找不到显示/隐藏微调器的相关事件。

如果它是相关的,我有一个ref小部件,可以使用它通过ref获取<input> myWidgetRef.inputRef字段。

5 个答案:

答案 0 :(得分:6)

您可以将change事件侦听器添加到输入引用,在选择文件时将调用该输入引用。

  

作为prop传递的onChange函数仅在上传完成时调用

然后使用onChange道具来处理处理完成。

Edit n5vk9z426p

import React from "react";
import { render } from "react-dom";
import Form from "react-jsonschema-form";
import FileWidget from "react-jsonschema-form/lib/components/widgets/FileWidget";

class MyForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      processing: false
    };
    this.inputChanged = this.inputChanged.bind(this);
  }

  inputChanged() {
    console.log("processing");
    this.setState({ processing: true });
  }

  componentDidMount() {
    this.fileWidget.inputRef.addEventListener("change", this.inputChanged);
  }

  componentWillUnmount() {
    this.fileWidget.inputRef.removeEventListener("change", this.inputChanged);
  }

  render() {
    return (
      <React.Fragment>
        <div>Is processing: {this.state.processing + ""}</div>
        <Form
          schema={{
            type: "object",
            properties: {
              file: {
                type: "string",
                format: "data-url"
              }
            }
          }}
          widgets={{
            FileWidget: props => (
              <FileWidget
                {...props}
                ref={ref => {
                  this.fileWidget = ref;
                }}
                onChange={() => {
                  console.log("processed");
                  this.setState({ processing: false });
                }}
              />
            )
          }}
          liveValidate
        />
      </React.Fragment>
    );
  }
}

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

答案 1 :(得分:3)

onChange = () => {
    this.setState({uploading: true})
    //upload fetch call
   fetch().then(results => {//this is dummy call
     this.setState({uploading: false})
   })
}

render() {
    const { multiple, id, readonly, disabled, autofocus } = this.props;
    const { filesInfo } = this.state;
    return (
      <div>
        <p>
        {this.state.uploading ? <div className="progress"></div> : null}
          <input
            ref={ref => (this.inputRef = ref)}
            id={id}
            type="file"
            disabled={readonly || disabled}
            onChange={this.onChange}
            defaultValue=""
            autoFocus={autofocus}
            multiple={multiple}
          />
        </p>
        <FilesInfo filesInfo={filesInfo} />
      </div>
    );
  }

答案 2 :(得分:0)

据我所知,你在客户端处理这个大文件。

因此,最简单的解决方案是在处理开始之前放置加载标志,并在处理结束后将其删除。

执行此操作后 - 您将遇到标记更改未反映到DOM状态,因为呈现是延迟的。

所以解决方案是转换代码:

setLoadingFlag();
doComputing();
removeLoadingFlag();

到异步形式:

setLoadingFlag();
setTimeout(() => {
    doComputing();
    removeLoadingFlag();
}, 0)

这将允许React渲染加载器

答案 3 :(得分:0)

你能做的是:

  1. 使用axios in react也显示文件加载的百分比。
  2. 创建一个简单的html绝对加载器,其中包含两个样式的元素,其中包含css:
  3. display:block;

    另一个将包含:

    display: none;
    

    给你的loader元素类名并用this.state更改它,这样当你开始上传文件时,你会将loader元素的classname改为包含display block样式的那个,然后在上传完成后再将它改回来。

    如果你想要完整的代码,请给我一条消息,我有一个。 Rohan Girdhani

答案 4 :(得分:0)

最简单的方法是使用main.html(具有主容器的文件)并添加一个这样的附加div。请注意,这个div注意到了旋转器的hcl css版本 <div class ="app-spinner" style="display: none" /> 请注意,默认情况下,微调器是隐藏的(显示:无);现在定义一个实用程序方法,它将打开和关闭微调器。像这样的东西

`
export const showLoader = (load) => {
load ? document.getElementsByClassName("app-spinner").style.display="block" : document.getElementsByClassName("app-spinner").style.display="none"
}
`

现在你所要做的就是在你输入类型文件的文件中导入showLoader

`
import { showLoader } from "../pathWhereTheUtilityMethodIsDeclared"
`

现在转到Input标记并添加一个onClick事件并触发这样的实用工具方法注意我们没有使用onChange

<input
            ref={ref => (this.inputRef = ref)}
            id={id}
            type="file"
            disabled={readonly || disabled}
            onChange={this.onChange}
            onClick={()=>{showLoader(true)}}
            defaultValue=""
            autoFocus={autofocus}
            multiple={multiple}
          />

onClick = {()=&gt; {showLoader(true)}}将在隐藏的微调器上切换,当完成对base64的编码时,只需使用false showLoader(false)调用该方法,这将确保隐藏微调器。 (注意确保在调用之前导入showloader,否则最终会出现未定义的错误)