简体   繁体   English

使用react / redux调用的最大堆栈大小

[英]Maximum stack size called using react/redux

I think I know what the problem is, but I am not sure how to fix it. 我想我知道问题出在哪里,但是我不确定如何解决。 I am wanting my state to update each time an "action/event/whatever" happens. 我希望每次发生“动作/事件/任何事件”时都更新我的状态。 I am trying to use componentWillReceiveProps, but then it's like my code goes into a never ending loop for some reason. 我正在尝试使用componentWillReceiveProps,但是由于某种原因,我的代码进入了永无止境的循环。

I have put two functions inside of this componentWillReceiveProps to be fire off each time something happens that way they will update. 我在这个componentWillReceiveProps里面放了两个函数,每次发生某种事情时,它们都会被触发。 I will post the code here: 我将在此处发布代码:

Just for information cart is an object that contains objects inside of it. 只是为了提供信息,购物车是一个内部包含对象的对象。 It gets more items if people so choose to add them and it can delete those items also. 如果人们选择添加这些项目,它将获得更多项目,并且也可以删除这些项目。

Component: 零件:

import React , { Component } from 'react';
import * as actions from '../../actions/cartActions';
import {Modal, Button} from 'react-bootstrap';
import {connect} from 'react-redux';
import _ from 'lodash';

class Cart extends Component {
  constructor() {
    super();
    this.state = {
      showModal: false,
    }

    this.getTotalAmount = this.getTotalAmount.bind(this);
  }

  componentWillReceiveProps(nextProps) {
    console.log(this.props.price);
    this.getTotalAmount(nextProps.cart);
    this.getTotalQuantity(nextProps.cart);
    return true;
  }

  open() {
    this.setState({
      showModal: true
    });
  }

  close() {
    this.setState({
      showModal: false
    });
  }

  getTotalAmount(cart) {
    this.props.addTotal(cart);
  }

  getTotalQuantity(cart) {
    this.props.getTotalQuantity(cart);
  }

  onDelete(_id) {
    this.props.deleteCartItem(_id);
  }

  onIncrement(_id) {
    this.props.updateCart(_id, 1);
  }

  onDecrement(_id, quantity) {
    if(quantity > 1) {
      this.props.updateCart(_id, -1)
    }
  }

  renderCart() {
    if(Object.keys(this.props.cart).length > 0) {
      const cartItemList = _.map(this.props.cart, (cartItem) => {
        return (
          <div key={cartItem._id} className="panel-body">
            <div className="well">
              <div className="row">
                <div className="col-xs-12 col-sm-2">
                  <h6>{cartItem.title}</h6><span>    </span>
                </div>
                <div className="col-xs-12 col-sm-2">
                  <h6>usd. {cartItem.price}</h6>
                </div>
                <div className="col-xs-12 col-sm-2">
                  <h6>qty. <label className="label label-success">{cartItem.quantity}</label></h6>
                </div>
                <div className="col-xs-6 col-sm-4">
                  <div className="btn-group" role="group">
                    <button
                      onClick={this.onDecrement.bind(this, cartItem._id, cartItem.quantity)}
                      className="btn btn-default btn-sm"
                    >-</button>
                    <button
                      onClick={this.onIncrement.bind(this, cartItem._id)}
                      className="btn btn-default btn-sm"
                    >+</button>
                    <span>     </span>
                    <button onClick={this.onDelete.bind(this, cartItem._id)} className="btn btn-danger btn-sm">Delete</button>
                  </div>
                </div>
              </div>
            </div>
          </div>
        );
      });
      return (
        <div className="panel-group">
          <div className="panel panel-primary">
            <div className="panel-heading">Cart</div>
            {cartItemList}
            <div className="row panel-body">
              <div className="col-xs-12">
                <h6>Total amount: {this.state.price.total}</h6>
                <button onClick={this.open.bind(this)} className="btn btn-success btn-sm">
                  PROCEED TO CHECKOUT
                </button>
              </div>
            </div>
            <Modal show={this.state.showModal} onHide={this.close.bind(this)}>
              <Modal.Header closeButton>
                <Modal.Title>Thank you!</Modal.Title>
              </Modal.Header>
              <Modal.Body>
                <h6>Your order has been saved</h6>
                <p>You will receive an email confirmation</p>
              </Modal.Body>
              <Modal.Footer>
                <div className="col-xs-6">
                  <h6>total $:</h6>
                </div>
                <Button onClick={this.close.bind(this)}>Close</Button>
              </Modal.Footer>
            </Modal>
          </div>
        </div>
      );
    } else {
      return (
        <div></div>
      );
    }
  }
  render() {

    return (
      <div>
        {this.renderCart()}
      </div>
    );
  }
}

function mapStateToProps(state){
  return {
    cart: state.cart,
    price: state.price
  };
}

export default connect(mapStateToProps, actions)(Cart);

Actions: 操作:

export function addTotal(cart) {
  return {
    type: "ADD_TOTAL_PRICE",
    payload: cart
  }
}
export function getTotalQuantity(cart) {
  return {
    type: "ADD_QUANTITY",
    payload: cart
  }
}

reducers: 减速器:

import _ from 'lodash';

export default function(state = [], action) {
  switch(action.type) {
    case "ADD_TOTAL_PRICE":
    let totalAmount = _.map(action.payload, (item) => {
      return item.quantity * item.price;
    }).reduce(function(a, b) {
      return a + b;
    }, 0).toFixed(2);
    return {...state, total: totalAmount}
    break;
    case "ADD_QUANTITY":
    let totalQuantity = _.map(action.payload, (item) => {
      return item.quantity;
    }).reduce(function(a, b) {
      return a + b;
    }, 0);
    return {...state, quantity: totalQuantity};
  }
  return state;
}

When you have function calls in componentWillReceiveProps , you generally need to have conditional logic around them so that they're only called if specific props are actually changing. 当您在componentWillReceiveProps进行函数调用时,通常需要在它们周围具有条件逻辑,以便仅在特定道具实际发生更改时才调用它们。 Typically, this looks like: 通常,这看起来像:

if(this.props.someProp !== nextProps.someProp) {
    // call some function only when the prop has changed
}

In your case, you're dispatching a Redux action every time the component receives any props, that dispatch causes a React re-render, and that repeats the cycle. 在您的情况下,您每次组件接收到任何道具时都将调度Redux操作,该调度会导致React重新渲染,并重复该循环。

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

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