Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Show/hide a spinner when file upload starts/finishes

I'm using this React component to upload files to the browser (not to a server). This component is part of the react-jsonschema-form library, so I can't change the source code. The render method of this component is shown below

  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>
    );
  }

This component accepts one or more files as input, base64 encodes them, and stores the encoded files in memory.

However, if the user chooses a large file (e.g. 5MB), there's a noticeable delay while processing. I would like to show a spinner when this processing starts and hide it when it finishes, but I can't find the relevant events on which to show/hide the spinner.

In case it's relevant, I have a ref to the widget, and can use this to get a ref to the <input> field via myWidgetRef.inputRef.

like image 912
Dónal Avatar asked May 09 '18 16:05

Dónal


2 Answers

You can add the change event listener to the input ref, which will be called when a file is selected.

onChange function passed as a prop is only called when the upload is finished

Then use the onChange prop for handling processing completion.

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"));
like image 55
Roy Wang Avatar answered Sep 19 '22 05:09

Roy Wang


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>
    );
  }
like image 35
Piyush Bhati Avatar answered Sep 20 '22 05:09

Piyush Bhati