2

I am implementing Dropzone area in React JS. I would like to display in a text field the file name that is currently being uploaded.

The problem is that react postpone calling render() method until the end of the forEach loop. The file names are logged dynamically (console.log) but the text field (dropzoneText) does not change in the view during the loop execution. After the end of the loop react render() the view with the last state - the last file name in the queue.

I found one case which seems to be similar using https://facebook.github.io/react/docs/clone-with-props.html feature, but it seems to be the workaround.

I would appreciate any help.

//...
import Dropzone from 'react-dropzone';

class SampleDropzone  extends React.Component{

    constructor(props, context) {
        console.log("Recruitment constructor");
        super(props, context);
        this.state = {
            dropzoneText: "Drop your files here..."
        };
    }

    wait(ms){
        var start = new Date().getTime();
        var end = start;
        while(end < start + ms) {
            end = new Date().getTime();
        }
    }

    onDrop(files) {

        files.forEach((file)=> {
            console.log('Received file: ', file.name);
            this.setState({dropzoneText: file.name});
            //this.saveFileToServerFromDropzone(file);
            this.wait(1000)
        });
    }

    render() {
    return(
        <div>
            <Dropzone onDrop={this.onDrop.bind(this)}>
            {this.state.dropzoneText}
            </Dropzone>
        </div>
    );
    }

};
  • Have you looked into `saga`? Here is a useful post, https://stackoverflow.com/questions/34570758/why-do-we-need-middleware-for-async-flow-in-redux/34623840#34623840 – garajo Aug 24 '16 at 08:11

1 Answers1

0

The drop can be moved to a setTimeout for the state updation to happen.

files.forEach((file)=> {
  console.log('Received file: ', file.name);
  this.setState({dropzoneText: file.name});
  setTimeout(() => {
    this.saveFileToServerFromDropzone(file);
    this.wait(1000);
  }, 100);
});
vijayst
  • 20,359
  • 18
  • 69
  • 113
  • The execution time of this.saveFileToServerFromDropzone(file) is not the case (I commented this line on purpose). The case is that "setState() does not immediately mutate this.state but creates a pending state transition." (https://facebook.github.io/react/docs/component-api.html). React performs optimization and renders the view after the end of the loop. As the result, the current state of the dropzoneText is not synchronized with the view. – Piotr Ładyżyński Aug 23 '16 at 20:08