1

UPD: I used React Dev Tools with Highlight Updates which seems to highlight each render() method call

I've written a simple React App which works the next way:

  1. It has a button and a list of numbers
  2. After clicking the button it adds a new number to the bottom of the list increased by 1 from the previous one

The problem is that React updates all list elements each time even when I use key property. I know that this problem can be solved by using PureComponents class or self-implemented shouldComponentUpdate()

Why React updates all list elements if they are not changed? I though that React uses special diffing algorithm for comparing elements and it should have worked, but now I see that it works not as I expected.

Could any body explain why React's diffing algorithm doesn't work in this case?

class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      numbers: [] 
    }

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

  handleButtonClick() {
    const numbers = this.state.numbers;
    const length = this.state.numbers.length ;
    const newNumber = length > 0 ? numbers[length - 1] + 1 : 0;

    this.setState({
      numbers: [...numbers, newNumber]
    })
  }

  render() {
    return (
      <div>
        <button onClick={this.handleButtonClick}>Add</button>
        <NumbersList numbers={this.state.numbers} />
      </div>
    );
  }
}


class NumbersList extends Component {
  render() {
    return (
      <ul>
        {
          this.props.numbers.map((number) => <NumberItem key={number} number={number} />)
        }
      </ul>
    )
  }
}

class NumberItem extends Component {
  render() {
    return (
      <li>{this.props.number}</li>
    )
  }
}
6
  • 1
    Are your keys unique? Commented Nov 12, 2018 at 12:58
  • @SergiuParaschiv Yes, they are. I don't think that it's a bug of my app Commented Nov 12, 2018 at 13:00
  • 1
    jsfiddle.net/zphfaoy4 - Using dev tools in Chrome on the Elements tab I don't see any DOM changes other than new <li> elements being added. Either I don't understand the question or I cannot reproduce this. Commented Nov 12, 2018 at 13:05
  • @SergiuParaschiv If try to use the React devtool extension and you turn on "Highlighting update" there it will show you that all elements are updated Commented Nov 12, 2018 at 13:11
  • 1
    Unfortunately React Dev Tools don't work in jsfiddle. But I am pretty sure that what the inspector shows is correct. Add a "break on subtree modifications" breakpoint on the <ul> and look through the process. You'll find that only the new <li> insertion happens. I guess React Dev Tools does something unexpected here. Commented Nov 12, 2018 at 13:18

2 Answers 2

1

The Javascript/React side uses shouldComponentUpdate to determine if it should rerender. This defaults to true and will rerender the component any time that there is a state change.

https://reactjs.org/docs/react-component.html#shouldcomponentupdate

Using this rerendered virtual representation of your app, it uses this https://reactjs.org/docs/reconciliation.html#the-diffing-algorithm to reconcile your virtualDOM with the real DOM

Sign up to request clarification or add additional context in comments.

2 Comments

I used React Dev Tools with Highlight Updates which seems to highlight each render() method call.
The render method is called when shouldComponentUpdate returns true. shouldComponentUpdate runs when state changes. That is independent of the actual dom being updated. The only way to affect that is to return false from shouldComponentUpdate, which should only be overridded when there is a serious performance issue.
0

Have you tried:

this.setState({numbers[index-1]: newNumber})?

Your code here:

this.setState({
  numbers: [...numbers, newNumber]
})

reads to me as a replacement of the numbers array and not an update of it.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.