我正在使用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
字段。
答案 0 :(得分:6)
您可以将change
事件侦听器添加到输入引用,在选择文件时将调用该输入引用。
作为prop传递的onChange函数仅在上传完成时调用
然后使用onChange
道具来处理处理完成。
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)
你能做的是:
display:block;
另一个将包含:
display: none;
给你的loader元素类名并用this.state更改它,这样当你开始上传文件时,你会将loader元素的classname改为包含display block样式的那个,然后在上传完成后再将它改回来。
如果你想要完整的代码,请给我一条消息,我有一个。 Rohan Girdhani
答案 4 :(得分:0)
<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,否则最终会出现未定义的错误)