React异步渲染组件,如何设置Loading效果?

渲染某个页面(组件),用到的数据需要通过ajax向后台获取,ajax方法一般写在componentDidMount里面,如果不做任何处理,请求数据之后会有一个rerender的过程,导致数据的展现很生硬,如下图:

clipboard.png

clipboard.png

网络慢的情况下,会先展示第一个页面,数据加载完成后,会“闪跳”到第二个页面,这种交互体验太烂了。。。

我想在数据加载完成之后再显示这个页面,加载之前,设置个loading效果,代码如下:

class Profile extends Component {
  constructor(props) {
    super(props);
    this.state = {
      loading: true
    };
  }

  componentDidMount() {
    // 数据异步请求,请求成功之后setState
    this.setState({
      loading: false
    })
  }

  render() {
    return (
      <div>
        {
          this.state.loading
          ? <div>加载中。。。</div>
          : <div>页面内容</div>
        }
      </div>
    )
  }
}

如果只有几个页面(组件),在每个页面写一下也无所谓,但是项目中会有很多个页面需要这样的loading,怎么样能统一设置下Loading效果而不用在每个页面都要写一遍?

项目中用到的有React、React Router、Redux,涉及到的方法都可以提一下,谢谢!

阅读 20.4k
4 个回答

哈哈,我们现在就是每个组件写一遍,我还真没想过优化的问题,借你的思路我说说我的第一反应。

所有的组件肯定都要有一个根部的容器,你可以在根部容器上设置一个:

<Slot>{ state.loading && toast+loading }</Slot>

然后修改ajax函数,做一个钩子,每次调用的时候,通过context设置这个属性为true,每次结束的时候再还原。
如果你想针对性的开启toast提示,可以做ajax函数上做扩展,默认打开,可以关闭钩子程序,就像jquery做的那样。

现在能想到的解决方案有两种:

1.对于整页的loading效果:我们现在是在每个Router组件外面套了一个HOC,可以在这个组件内部控制具体的渲染逻辑,比如说:先显示loading(转圈圈或者Placeholder),等首包返回数据后再进行整个页面的渲染。这样做就可以针对整个app都有一个统一的loading逻辑,但是这样也有个问题,就是可能没有一个很好的渐进性,首包如果慢的话,那么像题主页面中的静态部分(每个label等)可能没法先展现给用户;

2.针对单个组件的loading:可以把每行变成一个组件,这个组件内部可以先渲染静态部分,数据来之后利用css3进行有动画效果的渲染,这样可以更精确的控制渲染的逻辑。

直接在根组件里面放一个loading组件,然后哪里需要loading显示的话,直接dispatch一个showLoading的action不行吗?

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏