GeForce RTX 4090
GeForce RTX 4090

Reputation: 3498

React - serious performance problems when changing one list item

I have come across a serious performance problem. I have an application with a list of 2000 quite a big DOM structure list items and when I am changing one item in the list component like this:

changeOne:function(){
var permTodos = this.props.todos;
permTodos[Math.floor((Math.random() * 5) + 0)].todo=((Math.random() * 50) + 1);
this.setState({ todos: permTodos });
},

it rerenders all of the list items in the virtual DOM representation, and this is really slow. The same thing is done in Angular1 about 40 times faster. I have tried to implement shouldComponentUpdate for the list items

shouldComponentUpdate:function(nextProps, nextState){
return this.props.todo!==nextProps.todo;
},

but the this.props.todo is the same as nextProps.todo so nothing is changed. I have recreated a mini-version of my application in this fiddle https://jsfiddle.net/2Lk1hr6v/29/ and I am hoping there are som React experts out there who could help me with this unfortunate situation.

Upvotes: 0

Views: 63

Answers (2)

Aftab Khan
Aftab Khan

Reputation: 3923

Same edit here too, as mentioned in another thread.
Also I noticed two more things that I noticed in the fiddle here. In the TodoItem class, you have to say this.props.done not this.done.

render: function() {
    return <li onClick={this.props.done}>{this.props.todo}</li>
}

In the TodoList class, you are referring to this.done which is not declared. You should probably declare that function?.

{
      this.state.todos.map(function(todo) {
        return <TodoItem todo={todo} done={this.done} />
      }.bind(this))
}

Also switch to ES6 arrow functions! You don't have to bind this at the end of it. Code is much smaller and cleaner!!

{
      this.state.todos.map(todo => <TodoItem todo={todo} done={this.done} />)
}

Check out the edited fiddle: https://jsfiddle.net/2Lk1hr6v/33/
This should be now much faster than what it was!

PS: Explore other ES6 features here!!

Upvotes: 1

oklas
oklas

Reputation: 8220

You need to add unique key for each item from list:

this.state.todos.map(function(todo) {
  return <TodoItem key={todo.id} todo={todo} done={this.done} />
}.bind(this))

Key must be associated with item for example it may be its id. It must be not its index in list where are all items lies.

Upvotes: 2

Related Questions