简体   繁体   English

React - componentDidUpdate调用无限次

[英]React - componentDidUpdate called infinite times

I'm new to React and I feel I didn't catch the component lifecycle flow, this is the component I have: 我是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);

This is what I'm doing: inside the constructor the action fetchMyWishlist is called and it returns an array of book ids. 这就是我正在做的事情:在构造函数内部调用action fetchMyWishlist并返回一个book id数组。 The reducer updates the currentCart state with the result of fetchMyWishlist action. reducer使用fetchMyWishlist操作的结果更新currentCart状态。

First thing I don't understand is why in componentDidMount this.state.currentCart.payload is undefined. 首先我不明白为什么在componentDidMount中this.state.currentCart.payload是未定义的。 So I try to do my operations inside componentDidUpdate where this.state.currentCart.payload is defined and I can iterate through it. 所以我尝试在componentDidUpdate中执行我的操作,其中定义了this.state.currentCart.payload ,我可以遍历它。 Here for each book I try to retrieve additional information via fetchSpecificBook action. 对于每本书,我尝试通过fetchSpecificBook操作检索其他信息。 The problem here is that I get infinite number of action calls. 这里的问题是我获得了无数次的动作调用。 What I'd like to do is to store all additional books information into an array. 我想做的是将所有其他书籍信息存储到一个数组中。

How do I go about this? 我该怎么做?

Why in componentDidMount this.state.currentCart.payload is undefined? 为什么在componentDidMount中this.state.currentCart.payload是未定义的?

When you are inside a constructor, you can simply set the state like this: 当你在构造函数中时,你可以简单地设置这样的状态:

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

Your selector should give you the data you need as props() when the component is mounted. 您的选择器应该在安装组件时为您提供所需的数据作为props()。 Are you manipulating the store and therefore get new props which is resulting in an infinite re-render loop? 你是在操纵商店,因此得到新的道具,导致无限的重新渲染循环?

The constructor is not a good place to be fetching and setting state. 构造函数不是获取和设置状态的好地方。 I suspect that's the root of your issue. 我怀疑这是你问题的根源。 Try componentWillMount instead. 请尝试使用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);
  }
  1. don't call setState in constructo. 不要在constructo中调用setState。 you should use this.state = ... 你应该使用this.state = ...
  2. add this.componentDidMount = this.componentDidMount.bind(this) to constructor. 将this.componentDidMount = this.componentDidMount.bind(this)添加到构造函数中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM