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
.
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.
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"));
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>
);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With