React - componentDidUpdate调用无限次

时间:2017-04-21 11:21:18

标签: javascript reactjs

我是React的新手,我觉得我没有抓住组件生命周期流程,这是我的组件:

import React, {Component, PropTypes} from 'react';
import { connect } from 'react-redux';
import { fetchMyWishlist, fetchSpecificBook } from '../actions/index';

class Cart extends Component {

  static contextTypes = {
        router:PropTypes.object
    };

  constructor(props) {
    super(props);
    this.state = { currentCart:[], currentBook:[], wishlist:[] };

    var self = this;
    if (this.props.authenticated){
      this.props.fetchMyWishlist(this.props.signedInUserInfo._id).then(function(data){
        self.setState({ currentCart: data});
      });
    }
    else {
      this.context.router.push('/signin');
    }
  }

  componentWillMount(){}

  componentDidMount(){
    // I get undefined here
    console.log("component has been mounted: "+this.state.currentCart.payload);
  }

  componentDidUpdate(prevProps, prevState){
    var jsonObj = this.state.currentCart.payload;
    console.log("test: "+JSON.stringify(this.state.currentCart.payload));
    var self = this;
    if ((jsonObj) && (jsonObj.data)){   
      return jsonObj.data.map(function(book){
          self.props.fetchSpecificBook(book.itemID);
      });
    }
  }


  render() {
    console.log("rendering");

    return (
      <div>
        <div>
          <h3>Your wishlist</h3>
        </div>
      </div>
    );
  }
}

function mapStateToProps(state){
  return {
    currentCart: state.bookReducer.currentCart,
    currentBook: state.bookReducer.currentBook,
    authenticated: state.auth.authenticated,
    signedInUserInfo:state.auth.signedInUserInfo
  };
}

export default connect(mapStateToProps, {fetchMyWishlist, fetchSpecificBook})(Cart);

这就是我正在做的事情:在构造函数内部调用action fetchMyWishlist并返回一个book id数组。 reducer使用currentCart操作的结果更新fetchMyWishlist状态。

首先我不明白为什么componentDidMount this.state.currentCart.payload未定义。 所以我尝试在componentDidUpdate内部进行操作,其中定义了this.state.currentCart.payload,我可以迭代它。 对于每本书,我尝试通过fetchSpecificBook操作检索其他信息。 这里的问题是我获得了无数次的动作调用。 我想做的是将所有其他书籍信息存储到一个数组中。

我该如何解决这个问题?

3 个答案:

答案 0 :(得分:0)

  

为什么在componentDidMount中this.state.currentCart.payload未定义?

当你在构造函数中时,你可以简单地设置这样的状态:

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

当安装组件时,您的选择器应该为您提供所需的数据作为props()。你是在操纵商店,因此得到新的道具,导致无限的重新渲染循环?

答案 1 :(得分:0)

构造函数不是获取和设置状态的好地方。我怀疑这是你问题的根源。请改为componentWillMount

  state = {
    currentCart: [],
    currentBook: [],
    widhlist: []
  };

  componentWillMount() {
    const { authenticated, fetchMyWishlist, signedInUserInfo } = this.props;

    if (authenticated){
      fetchMyWishlist(signedInUserInfo._id).then(function(data){
        this.setState({ currentCart: data});
      });
    }
  }

  componentDidMount(){
    console.log("component has been mounted: "+this.state.currentCart.payload);
  }

答案 2 :(得分:-1)

  1. 不要在constructo中调用setState。你应该使用this.state = ...
  2. 将this.componentDidMount = this.componentDidMount.bind(this)添加到构造函数。