Best way to show a loading spinner/gif while my React component is fetching via AJAX?

后端 未结 3 519
醉梦人生
醉梦人生 2021-02-06 03:51

Imagine I have a very simple React component that shows a list of elements that are stored in this.state.myList (see example below)

Hitting a \"Refresh\" bu

相关标签:
3条回答
  • 2021-02-06 04:03

    small edit from @Tom's answer above.

    render: function() {
        return (
            <div className="container">
                <ul>
                    {
                        this.state.fetchInProgress ?
                            <Spinner />
                        :
                            this.state.myList.map(function(item) {
                                return <li id="{item.id}">{item.name}</li>
                            })
                    }
                </ul>
    
                <input type="submit" value="REFRESH LIST" onClick={this.handleButtonClick} />
            </div>
        );
    }
    
    0 讨论(0)
  • 2021-02-06 04:06

    The React model is built around having UI as a representation of your state. That means you should model your state as "what is the necessary data" and the return value of render() is just how you display that data.

    In your case, you should keep track of isLoading and in render() you conditionally display the spinner based on the value in your state.

    var Foo = React.createClass({
      getInitialState: function() {
        return {isLoading: false};
      },
      handleButtonClick: function() {
        this.setState({ isLoading: true });
        return $.ajax({
          type: "POST",
          url: "/some/refresh/url",
          data: JSON.stringify({}),
          dataType: "json",
          contentType: "application/json",
          success: (function(response){
            self.setState({ myList: response.list, isLoading: false });
          })
        });
      },
    
      render: function() {
        return (
          <div className="container">
            <ul>
              {
                this.state.myList.map(function(item) {
                  return <li id="{item.id}">{item.name}</li>
                });
              }
            </ul>
    
            {this.state.isLoading && <Spinner />}
    
            <input type="submit" value="REFRESH LIST" onClick={this.handleButtonClick} />
          </div>
        );
      }
    });
    
    0 讨论(0)
  • 2021-02-06 04:12

    The way I always solve this is for the component to track fetchInProgress in its state.

    Before you make your fetch, you set this value to true; when the fetch completes (either success or fail), you set the value back to false.

    The component's render method then honors this flag; if the flag is true, it renders a spinner instead of a dataset.

    var Foo = React.createClass({
        handleButtonClick: function() {
    
            // before making call, set fetch flag
            self.setState({ fetchInProgress: true });
    
            return $.ajax({
                type: "POST",
                url: "/some/refresh/url",
                data: JSON.stringify({}),
                dataType: "json",
                contentType: "application/json",
                success: (function(response) {
                    // when updating with dataset, also reset fetch flag
                    self.setState({
                        fetchInProgress: false,
                        myList: response.list
                    });
                }),
                failure: ((function(reason) {
                    // make sure to reset even if fetch fails!
                    self.setState({
                        fetchInProgress: false
                    });
                })
            });
        },
    
        render: function() {
            return (
                <div className="container">
                    <ul>
                        {
                            this.state.fetchInProgress
                                : <Spinner />
                                : this.state.myList.map(function(item) {
                                        return <li id="{item.id}">{item.name}</li>
                                    })
                        }
                    </ul>
    
                    <input type="submit" value="REFRESH LIST" onClick={this.handleButtonClick} />
                </div>
            );
        }
    });
    
    0 讨论(0)
提交回复
热议问题