知道在React / Redux中UI何时就绪

时间:2017-09-25 20:37:24

标签: javascript reactjs web redux react-redux

我想知道我的应用需要多长时间才能成为"准备好"供用户与之互动。应用加载的时间表包括以下内容:

  1. DOM加载。
  2. 初始反应渲染。
  3. 从各种componentDidMount() s
  4. 触发的HTTP调用
  5. HTTP调用返回。 Redux状态使用HTTP响应进行更新。
  6. 使用HTTP响应中的新值进行React渲染。
  7. 所有初始加载完成。用户已准备好与应用程序进行交互。
  8. 在此过程结束时,我想发起跟踪事件以记录window.performance.now()的值。

    我不确定最好的方法是什么。 React的组件系统可以很好地解耦UI的各个部分。在这种情况下,不幸的是,它意味着我不会有一个容易检查的地方知道"所有内容都使用新数据进行渲染"。

    我尝试或考虑的事情:

    1. 查找React生命周期挂钩,告诉我是否有任何孩子正在更新。像componentOrAnyChildDidUpdate()这样的东西。我不认为这存在,这可能与React哲学背道而驰。
    2. 通过anyChildDidUpdate()context生命周期钩子绑定在一起,并使我的应用程序中的每个组件都成为辅助抽象基类的子类,或者包含在更高阶的组件中。这似乎很糟糕,因为contextexperimental API
    3. 通过store.subscribe()订阅Redux州。更新Redux状态以显示是否已返回所有HTTP调用。一旦所有的HTTP调用都返回,并且React完成了重新渲染,那么我就知道要触发跟踪回调。问题是知道React何时完成重新渲染。如果我的store.subscribe()回调保证在react-redux的回调后同步执行,则会有效。但事实并非如此。
    4. 在React中有一个很好的方法吗?

6 个答案:

答案 0 :(得分:1)

我担心在React中没有一个普遍好的方法可以做到这一点,这就是"逻辑"这与您的申请结构有关。

我希望在单页应用程序(SPA)中从一个页面导航到另一个页面时显示一个加载程序,并且我遇到类似的问题,不知道何时停止显示它以及新页面中的所有组件是否都已完成他们的API调用/渲染。

我解决它的方式是:

1)我从组件内部删除了所有API调用。

2)创建一个Page组件来包装该页面中包含的所有组件(由您的react路由器调用)。

3)在导航时同时执行组件所需的所有请求(在我的情况下显示加载器时)。对于每个完成的请求,创建一个promise并在其中使用React.createElement动态创建组件。传递给创建请求响应的组件和promise处理程序作为道具。

4)解决组件componentDidMount中的承诺。

5)一旦所有的承诺得到解决,你就会知道"页面"准备就绪,您可以记录window.performance.now()

的值

如果没有大量的上下文代码,很难提供最小的代码示例,因为此代码遍布应用程序。

答案 1 :(得分:1)

有不止一种方法可以做你要求的事情 - 但是我会做到以下几点:

•创建一个perf reducer并在我创建redux存储之前调用performance.now()并将值添加到初始状态。

{ perf: { start: '...', end: '...' } }

•在加载的reducer中跟踪初始HTTP请求的加载状态。

{ loaded: { request1: false, request2: false, request3: false } }

•将顶级组件连接到已加载的reducer,并检查componentDidUpdate中是否所有请求都已完成。如果为true,则将最终值添加到perf reducer。

import React from 'react';
import { connect } from 'react-redux';

class App extends React.Component {
  componentDidUpdate(prevProps) {
    if (!prevProps.loadingComplete && this.props.loadingComplete) {
      this.props.updatePerf(performance.now());
    }
  }
}

const mapStateToProps = state => ({
  loadingComplete: state.loaded.every(item => item),
});

const mapDispatchToProps = dispatch => ({
  updatePerf(time) {
    dispatch({ type: 'SET_ENDING_PERF', payload: time });
  },
});

export default connect(mapStateToProps, mapDispatchToProps)(App);

答案 2 :(得分:0)

在我们的项目中,我们使用redux和一些操作 - 触发器,请求,成功,错误。

"触发"调用request和throw loading:true进入我们的" smart"零件 "请求"获取数据并将其抛入Success / Error "成功",告诉我们一切正常,加载数据并抛出{loading:false,data}

成功/错误时,我们总是知道我们的应用程序正在发生

当然,您可以使用componentWillReceiveProps(nextProps){}并检查组件中的加载标志和数据

答案 3 :(得分:0)

您可以尝试使用react-addons-perf

这就是我通常对应用程序进行基准测试的方式:

基本上,您希望在组件开始更新时开始测量,并在生命周期方法componentDidUpdate()之后停止测量。

import Perf from 'react-addons-perf'

componentWillMount() {
  window.performance.mark('My app');
 }
componentDidMount() {
  console.log(window.performance.now('My app'));
  Perf.start()
  // ... do your HTTP requests
}
componentDidUpdate() {
 Perf.stop();
 Perf.printInclusive();
}

就像那样,您将跟踪组件初始渲染+组件更新。

希望有所帮助

答案 4 :(得分:0)

实现这一目标的两个步骤。

通过操作跟踪所有HTTP请求

简化计数器在redux状态就足够了,在请求开始时递增,在成功或失败时递减(所有这些都通过适当的操作)。 丹·阿布拉莫夫面前没有window.dirty.stuff

跟踪所有 connect ed 组件

componentDidUpdate方法表示所有孩子都完成了渲染。这可以通过recompose lifecycle HOC没有太多样板来实现。如果您已使用sCU s cWRPrecompose,则开始跟踪重新渲染的正确位置可能是shouldUpdate方法,或仅reselect - 因为我们赢了&#39 ; t跟踪没有更新的组件。

请注意,所有都是假设惯用的react / redux app,没有棘手的副作用或动画。例如,如果层次结构深处的某个子组件触发其自己的AJAX请求,请在cDM上,而不是通过redux操作。这样你也必须跟踪它们,但是没有人能确定它们是否暗示任何重新渲染。 跟踪此类行为仍然是可能的,可能需要更多努力。

答案 5 :(得分:0)

来自设计POV,在我看来是否准备就绪是一个用户表示属性,所以应该由反应组件单独处理。

例如,您可能稍后决定允许用户与某些其他部分仍在加载时与UI的某些部分进行交互,或者您可能决定某些组件应该允许用户在数据模型准备好之前进行交互,等等......换句话说,它是(响应)组件的责任,以判断它是否准备就绪,没有其他人。

也就是说,所有人都可以等待'组件可以暴露一个 onLoad -like prop来传递反应树;然后,根组件将通过相应地将适当的道具传播到叶子来相应地更改树向下来协调结果。

这可以通过编写mixin / high命令组件来实现,以填充"准备更新"逻辑。