为什么在渲染后调用 componentWillMount?

IT技术 javascript reactjs
2021-05-17 17:40:22

我正在使用 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},第二次渲染,触发这个>>> Object {params: Object, query: Object, dealerData: Object},这正是我需要的。

那么,为什么componentWillMount要等待渲染方法才能被解雇?

1个回答

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

这是您的示例中发生的操作序列的近似值:

  1. componentWillMount调用getDealers命令(这是异步的)
  2. 初始render具有默认组件状态
  3. 在动作创建者和存储中完成的异步操作用dealer数据设置
  4. store 发布changed事件,重新触发渲染
  5. 第二个render调用dealer组件状态数据。

问题是 React 会按照一定的顺序运行它的生命周期方法,而不关心你调用一些异步方法。所以基本上你没有办法停止rendering仅仅因为你调用了一个命令来获取dealers. 这是react(或功能)的限制,当与异步编程结合时会出现,您应该按原样接受它。

如果你接受 React 会渲染两次的事实,你可以利用loading它对你有利,所以在第一次渲染时你可以只显示一个指示器(例如一个旋转轮),当数据加载时你只在第二个中显示它render

但是,如果您不相信并且仍想避免在初始加载时进行双重渲染,则可以在挂载应用程序组件之前对数据进行预取,这将确保在第一次加载之前将初始数据加载到 store 中render,即这意味着您不必调用getDealersincomponentWillMount因为数据已经在第一个render.

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