为 React JS Ajax 调用创建加载动画的最佳方法是什么?

What is the best way to create a Loading Animation for React JS Ajax calls?

我有一个 React JS (16.13.1) 应用程序 - 我有兴趣创建一些加载动画以在加载该内容时显示在容器中。我希望以一种可以提供一些可重用性的方式来做到这一点,如下例所示:

import React from "react";
...
import axios from "axios";
import LoadingAnimation from "[myloadinganimation]"

class Widget extends React.Component {
    constructor(props) {
        super(props);
        this.state = { widgets: [] };
    }

    getWidgets() {
        const data = new FormData();
        return axios.post('/my/api/url', data, window.globals.formPostHeaders)
               .then(res => {
                    const regions = res.data.regions.map(obj => obj);
                    this.setState({regions});
               });
        
    }


    render() {
         return (
              <>
                 <Table>
                     <tbody>
                     <tr>
                         <!-- desired component -->
                         <LoadingAnimation self={this} conds={{obj: this, cb: 'callback?'}} />
                         <!-- /desired component -->
                     </tr>
                     </tbody>
                 </Table>
              <>
         );

    }

}

理论上,我会拥有一个名为 LoadingAnimation 的组件,它可以在此页面上调用 - 最好是在页面加载时调用,或者甚至只是在启动 AJAX 请求时调用。我意识到这需要听众、回调和 Promise 的某种组合才能做到这一点。我只是想不出正确的 flow/order 来显示它。

为了使其可重用,我会让组件显示动画,监听 ajax 请求的完成,然后将数据传递给 callback 在视图组件中进行渲染;以便将提升从动画组件中抽象出来,但是处理事件的调度或者它们可能是什么。

我怎样才能做到这一点?

我不确定我是否得到了可重复使用的部分。处理加载最直接的方法是在状态中处理它(如下所示)。我不知道它是否适合你:

class Widget extends React.Component {
  constructor(props) {
    super(props);
    this.state = { widgets: [], loading : false };
  }

  componentDidMount() {
    // to trigger on page load
    this.getWidgets()
  }

  async getWidgets() {
    this.setState({ loading: true})
    const data = new FormData();
    await axios.post('/my/api/url', data, window.globals.formPostHeaders)
      .then(res => {
        const regions = res.data.regions.map(obj => obj);
        this.setState({ regions });
      });
    this.setState({ loading : false})
  }


  render() {
    return (
            <>
              <Table>
                <tbody>
                  <tr>
                    { this.state.loading && <LoadingAnimation />}
                  </tr>
                </tbody>
              </Table>
            <>
          );
       }
}

如果你想在不同的地方重复使用它,你最好寻找一种方法来将加载状态分散到你想要重复使用的组件和地方。您可以使用 redux 或 flux 库来处理此类情况的状态。还有内置的 Context API 可能也很有用。