简体   繁体   中英

nextProps always identical to this.props in componentWillReceiveProps, even when the props have changed

I have a component in my React app that renders a total value for the user. When that value goes up, I want to play a noise. I figured that within the component that displays the total would be a good place to play that noise from.

So I added a componentWillReceiveProps method to the component, and in it, I calculate two totals: total is calculated from this.props and nextTotal is calculated from nextProps .

To my surprise, even when the values change, and the totals change, nextTotal and total are always the same. So the conditional that I want firing when the total goes up never happens.

I wrote up a simple, single-component example. JSfiddle .

var Hello = React.createClass({
  componentWillReceiveProps: function(nextProps) {
    var total = 0;
    this.props.vals.forEach(val => total+= val);

    var nextTotal = 0;
    nextProps.vals.forEach(val => nextTotal+= val);

        console.log(total, nextTotal)

    if (nextTotal > total) {
            //never runs
            console.log('moving up');
        }
  },
  render: function() {
    var total = 0;
    vals.forEach(val => total+= val)
    return (
        <div>{total}</div>
    )
  }
});

var vals = [1, 21, 452, 123];

setInterval(renderReact, 1000)

function renderReact() {
    vals.push(10);
  ReactDOM.render(
    <Hello
      vals={vals}
    />,
    document.getElementById('container')
  );
}

As you can see, every second it adds 10 to the vals array, which means the total moves up by 1. But if you open the console, you can see that total and nextTotal are always the same, and moving up never gets logged.

I'm clearly misunderstanding something , and if anyone could explain what my misunderstanding is, and how I should achieve what I'm going for, that would be fantastic.

As noted in the comments (by @PitaJ), your problem is that you're passing in an array the first time, and then ALTERING the array - rather than calling with a new property. You've reached into the object your component is holding a reference to as its existing property and changed the contents of it.

In your fiddle, try this:

function renderReact() {
    vals.push(10);
  ReactDOM.render(
    <Hello
      vals={vals.concat([])}
    />,
    document.getElementById('container')
  );
}

Passing a copy of the array in as your prop each time, you'll see they differ appropriately.

This is actually a non-trivial source of error in using react, and can crop up even when using redux with it if reducers aren't carefully written. Using immutable data structures is one way to avoid it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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