Dave Stein
Dave Stein

Reputation: 9316

Why is shouldComponentUpdate saying current props are new props in React?

I am using Redux, but not sure that this would be the cause.

I have code like this

<Page>
  <AnotherChild />
  <Pricing quotes={this.props.item.quotes} />
</Page>

<Pricing> has a child component that fires a dispatch on change of an input, which updates prices of item.

<Pricing> has this:

shouldComponentUpdate(nextProps, nextState) {
  console.log(nextProps.quotes[0].value, this.props.quotes[0].value);
}

So let's say the input has 10, I highlight all and press 5, the logs show 5 for both the next and current prop values.

Confused how that is the case. I would think I'd need to see a log of 10 -> 5 at some point because it starts at 10 and couldn't magically switch from a parent, right?

EDIT

Here is a code block that is triggering the prop change.

_updateDiscountAmount() {
  var discountAmount = +this.refs.discount_amount.getValue();

  var quotes = this.props.quotes.map(quote => {

    var promoPrice = quote.value;

    if (Number.isNaN(discountAmount)) {
      discountAmount = 0;
    }

    quote.percentage = discountAmount;

    promoPrice = (promoPrice - (promoPrice * discountAmount/100)).toFixed(2);

    return quote;
  });


  this.props.dispatch({
    type: 'CURRENT_PAGE_UPDATE',
    data: {
      discount_amount: discountAmount,
      quotes
    }
  });
},

Upvotes: 0

Views: 606

Answers (2)

wintvelt
wintvelt

Reputation: 14101

When your nextProps appear to be the same as this.props, then usually you somewhere mutate props unintentionally. In an example:

// this.props.quotes = [ { discount : 5 }, { discount : 3}];
var quote = this.props.quotes[0];
console.log(quote.discount);               // 5
quote.discount = 10;                       // (!) this also updates props
console.log(this.props.quotes[0].discount); // 10

To fix, make a copy of the object before you update, like so:

var newQuotes = this.props.quotes.map(quote => {

  // Copy object
  var newQuote = Object.assign({}, quote);
  ...
  newQuote.percentage = discountAmount;
  ...
  return newQuote;
});

Upvotes: 3

Dave Stein
Dave Stein

Reputation: 9316

@wintvelt above gave the answer so if he writes it in, I will mark it.

Basically the above code is failing. Even though I am mapping to a new array, I am changing what should be unmutable.

All I needed to do to fix the problem was make a copy of quote within the loop before modifying it.

ie:

var quotes = this.props.quotes.map(quote => {

  // Copy the object here
  quote = Object.assign({}, quote);

  var promoPrice = quote.value;

  if (Number.isNaN(discountAmount)) {
    discountAmount = 0;
  }

  quote.percentage = discountAmount;

  promoPrice = (promoPrice - (promoPrice * discountAmount/100)).toFixed(2);

  return quote;
});

Upvotes: 1

Related Questions