Material-UI LinearProgress 栏不工作

Material-UI LinearProgress bar not working

我有一个简单的文件上传实用程序,我正在使用 react-dropzone,并且我想结合它使用 material-ui LinearProgress 条来显示进度。

下面显示的是我创建的组件,它呈现文件上传实用程序以及 LinearProgress 栏。

我正在使用 superagent 库使用多部分表单数据将后台文件实际上传到后端。 superagent 的请求允许回调或事件处理程序用于上传进度。在我的代码中,进度事件处理程序被成功调用并由 console.log 语句证明。在每次调用进度时,我都会更新 LinearProgress 栏使用的 this.state.completed 属性。

问题是进度条没有向前移动。我肯定遗漏了一些非常简单的东西。

非常感谢任何帮助,在此先感谢您。

import React, {Component} from 'react';
import Dropzone from 'react-dropzone';
import request from 'superagent';
import LinearProgress from 'material-ui/LinearProgress';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';

export default class MultiFileUpload extends Component {
    constructor(props) {
      super(props);

      this.state = {
        completed: 0,
      };

    }
 
    onDrop(files) {
      console.log('Received files: ', files);
      this.state.completed = 0;
      var data = new FormData();
      var req = request.post('/nltools/v1/files/upload');
      files.forEach((file)=> {
          data.append('files[]', file, file.name);
      });
      
      req.on('progress', (p) => {
        console.log('Last percentage', this.state.completed);
        var percent = Math.floor(p.percent);
        if (percent >= 100) {
          this.setState({completed: 100});
          console.log('Done 100%');
        } else {
          this.setState({completed: percent});
          this.state.completed = percent;
          console.log('Percentage done: ', percent);
        }
       });

      req.send(data);
      req.end(function(err, res){
          this.state.completed = 0;
          console.log("Successfully uploaded");
      });
    }

    render() {
      var thisStyle = {
  borderWidth: 4,
  borderColor: "orange",
  borderStyle: "dashed",
  borderRadius: 4,
  margin: 30,
  padding: 30,
  height: 300,
  transition: "all 0.5s"
      };
      
      var progressStyle = {
        margin: 30,
        passing: 30,
      };

      return (
        <div>
          <div style={progressStyle}>
            <MuiThemeProvider>
              <LinearProgress color="orange" mode="determinate" value={this.state.completed} />
            </MuiThemeProvider>
          </div>
          <Dropzone onDrop={this.onDrop} className="dropzone-box" style={thisStyle}>
            <div>Try dropping some files here, or click to select files to upload. {this.state.completed}</div>
          </Dropzone>

        </div>
      );
    }
}

首先,我认为你的问题可能是这样的:

onDrop={this.onDrop}

应该是

onDrop={files => this.onDrop(files)}

或...

onDrop={this.onDrop.bind(this)}

或...

constructor(props) {
  super(props);

  this.state = {
    completed: 0,
  };

  this.onDropHandler = this.onDrop.bind(this);
}

// ... then on your component:
onDrop={this.onDropHandler}

...否则,您在 onDrop() 中的所有 "this" 引用都将不正确,因此 "this.state" 和 "this.setState" 将失败。

而且,你永远不应该直接改变你的状态。始终使用 setState()。因此,删除所有这样的调用:

this.state.completed = ???;

总是这样做:

this.setState({ completed: ??? });

此外,setState 是异步的。所以,如果你需要在状态更新后才触发某些东西,你可以传递一个回调函数作为第二个参数:

this.setState({ completed: 75 }, () => { console.log('state.completed is now 75'));
// ^^ Immediately after the above call state.completed is probably not 75 yet,
// because setState() is async

最后,请特别注意您的 req.end() 调用。在那里,你 only 改变状态(再次,这很糟糕)并且你根本没有调用 .setState() (因此,组件不会在 req.end())

完整示例:

import React, { Component } from "react";
import ReactDOM from "react-dom";
import Dropzone from "react-dropzone";
import request from "superagent";
import { Line } from 'rc-progress';

class App extends Component {
  state = {
      completed: 0
  }

  onDrop = files => {
    this.setState({ completed: 0 });
    var data = new FormData();
    files.forEach(file => {
      data.append("files[]", file, file.name);
    });

    var req = request.post("http://localhost:3001");
    req.on('progress', event => {
      var percent = Math.floor(event.percent);
      if (percent >= 100) {
        this.setState({ completed: 100 });
      } else {
        this.setState({ completed: percent });
      }
    });

    const that = this;
    req.send(data);
    req.end((err, res) => {
      console.log("Successfully uploaded");
    });
  };

  render() {
    const divStyle = {
      border: '1px solid black'
    };
    return (
      <div style={divStyle}>
        <Dropzone onDrop={this.onDrop} className="dropzone-box">
          <div>Try dropping some files here, or click to select files to upload. {this.state.completed}</div>
          <Line percent={this.state.completed} strokeWidth="0.5" strokeColor="#2db7f5" strokeLinecap="square" />
        </Dropzone>
      </div>
    );
  }
}

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