为什么在渲染后调用componentWillMount?

时间:2015-10-08 20:31:35

标签: javascript reactjs

我正在使用React,我正在努力了解生命周期。我正在做一个componentWillMount方法,以便在渲染发生之前获得我需要的props。我需要知道在加载视图时如何更新状态。

我要做的只是GET请求,以获取赌场游戏的经销商列表。基本上,我缺少1或2个步骤来渲染经销商在DOM中的列表

我将展示我在使用我的代码做什么,之后我将解释我想要的内容

行动部分

getDealerActions.js

class GetDealersActions {

  constructor () {
    this.generateActions('dealerDataSuccess', 'dealerDataFail');
  }

  getDealers (data) {
    const that = this;
    that.dispatch();
    axios.get('someroute/get-dealers/get-dealers')
      .then(function success (response) {
        that.actions.dealerDataSuccess({...response.data});
      })
  }
};
然后我们搬到商店

getDealersStore.js

class GetDealersStore {

  constructor () {
    this.state = {
      dealerData : null,
    };
  }

  @bind(GetDealersActions.dealerDataSuccess)
  dealerDataSuccess (data) {
    this.setState({
      dealerData : data,
    });
   console.log(this.state.dealerData);
  }
}

在这种情况下,console.log(this.state.dealerData);会返回类似这样的内容,这正是我需要的内容

Object {dealersData: Array[3]}

问题出现在组件部分,老实说,因为我不知道如何处理这里的数据

@connectToStores
export default class Dealers extends Component {

  static contextTypes = {
    router : React.PropTypes.func,
  }

  constructor (props) {
    super(props);
    this.state = {}
  }

  static getStores () {
    return [ GetDealersStore ];
  }

  static getPropsFromStores () {
    return GetDealersStore.getState();
  }

  componentWillMount () {
    console.log('@@@', this.props);
    GetDealersActions.getDealers();
  }

  render () {
    console.log('>>>', this.props);
    let content;
    if (this.state.dealerData) {
      content = this.state.dealerData.map((item) => {
        return <div key={item.CardId}>{item}</div>;
      });
    } else {
      content = <div>Loading . . .</div>;
    }

    return (
      <div>
        <div>{content}</div>
      </div>
    );
  }

}

我到达<div>{content}</div>的所有内容都是Loading . . .,因为this.state就是这样Object {}

我得到的一个奇怪的情况是,这个视图渲染两次,第一次渲染,console.log('>>>', this.props);返回此>>> Object {params: Object, query: Object},第二次渲染,触发此{{} 1}}这就是我需要的。

那么,为什么>>> Object {params: Object, query: Object, dealerData: Object}正在等待渲染方法才能被触发?

1 个答案:

答案 0 :(得分:6)

这根本不奇怪。 componentWillMount将在渲染之前触发,在第一遍中,您将调用一个操作来获取经销商GetDealersActions.getDealers();,这基本上是异步命令。由于它是异步的,因此组件在获取数据之前将呈现一次,然后在商店发布changed事件之后再次呈现,这将重新触发呈现。

以下是示例中发生的动作序列的近似值:

  1. componentWillMount调用getDealers命令(异步)
  2. 初始render,默认组件状态
  3. 在动作创建者和商店中完成的异步操作设置为dealer数据
  4. 商店发布changed事件,重新触发呈现
  5. 使用组件状态中的render数据调用第二个dealer
  6. 问题是React会以某种顺序运行它的生命周期方法,而不是关心你调用一些异步方法。所以基本上你没有办法停止rendering因为你调用了一个命令来获取dealers。这是react(或一个特性)的限制,当与异步编程结合使用时会出现,你应该按原样接受它。

    如果您接受React将渲染两次的事实,您可以利用它对您有利,所以首先渲染您可以只显示loading指示符(例如旋转轮),当数据加载时将其显示在第二个render

    但是,如果您不相信并且仍然希望避免在初始加载中进行双重渲染,则可以在安装应用程序组件之前预取数据,这样可以确保在存储之前将初始数据加载到存储中。第一个render,这意味着您不必在getDealers中调用componentWillMount,因为数据已经存储在第一个render的商店中。

    提醒一下,双重渲染不是一个重要的性能问题,就像它在Angular.js或Ember.js中一样,因为React在DOM操作方面非常有效,但如果处理不当,它可能会产生一些UX问题