Вопрос

I am trying to have a "Loading" message appear before a time consuming operation takes place in React. I tried this:

var LoadingExample1 = React.createClass({
    getInitialState: function () {
        return {message: ""};
    },
    render: function () {
        return (
            <div>
                <div>{this.state.message}</div>
                <button onClick={this.doWork}>Solve</button>
            </div>
            )
    },
    doWork: function () {
        this.setState({message: "Loading..."});

        for (var i = 0; i < 1000000000; i++) {
            ;
        }

        this.setState({message: "Done."});
    }
});

React.renderComponent(
    <LoadingExample1 />,
    document.getElementById("example1")
);

But it seems that the UI is updated only after the operation has been completed, which is too late. I also tried using the setState callback, but the result is the same:

var LoadingExample2 = React.createClass({
    getInitialState: function () {
        return {message: ""};
    },
    render: function () {
        return (
            <div>
                <div>{this.state.message}</div>
                <button onClick={this.doWork}>Solve</button>
            </div>
            )
    },
    doWork: function () {
        this.setState({message: "Loading..."}, function () {

            for (var i = 0; i < 1000000000; i++) {
                ;
            }

            this.setState({message: "Done."});
        });
    }
});

React.renderComponent(
    <LoadingExample2 />,
    document.getElementById("example2")
);

Any suggestions on what to try next?

Это было полезно?

Решение

This is what I would do. I'd be interested in hearing if there is a better approach.

var LoadingExample3 = React.createClass({
    getInitialState: function () {
        return {message: ""};
    },
    render: function () {
        return (
            <div>
                <div>{this.state.message}</div>
                <button onClick={this.doWork}>Solve</button>
            </div>
            )
    },
    doWork: function () {
        this.setState({message: "Loading..."});
        this.doWorkAsync();
    },
    doWorkAsync: function () {
        var self = this;
        setTimeout(function() {

            for (var i = 0; i < 1000000000; i++) {
                ;
            }

            self.setState({message: "Done."});
        }, 0); // timeout of 0 ms means "run at the end of the current event loop"
    }
});

React.renderComponent(
    <LoadingExample3 />,
    document.getElementById("example1")
);
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top