stratis
stratis

Reputation: 8042

Rendering optimization using nested state in React

I have a React app where I believe -though not certain- that "nested state" causes me delays.

Here's the thing:

I keep my state in a variable called dataset.

dataset is an array of objects like this:

(5) [{…}, {…}, {…}, {…}, {…}]

and each object has the following structure:

{id: '5', name: 'Bob', url: 'http://example.com', paid: 'yes'}

Finally my render method displays the data in a table:

...
{dataset.map((entry) => (
    ...
    <tr id={entry.id}><td>{entry.name} has paid: {entry.paid}</td></tr>
    ...
))}

It all seems to be working fine but then whenever I need to update the state because presumably user number 5 didn't pay this month I do this:

// copy current state
let new_dataset = this.state.dataset.slice(); 

// modify the copy
new_dataset[5].paid = !this.state.dataset[5].paid;

// replace old state with the modified copy
this.setState({
    dataset: new_dataset
});

However here's the problem:

Will React update all 5 rows or just the row holding the object I modified?

Wouldn't it be a waste to have react update 10000 rows just for a small change in one row? What's the best practice for such scenarios?

Thanks in advance.

P.S. I have already looked at how to Avoid Reconciliation but I'm not sure how to apply in this case.

Upvotes: 2

Views: 507

Answers (3)

Chris
Chris

Reputation: 59491

Will React update all 5 rows or just the row holding the object I modified?

It will only update the DOM with what's been changed, however it will still iterate through all your items in your dataset array. The iteration as well as the reconciliation process itself would take time if there are that many items in your array.

So the problem here isn't really the implementation per se - it's a very common approach for small to medium sized arrays. However, if you indeed have large entries in your array, you may notice performance hits, in which case you might want to find a different implementation.


That said, I did find a minor error in your code:

You correctly create a copy of your array with this.state.dataset.slice(); however you are not creating a copy of the object that you are mutating. So essenatially you are mutating the state directly. So instead do:

// copy current state
let new_dataset = this.state.dataset.slice(); 

// copy the object
let obj = Object.assign({}, new_dataset[5]);

// modify the copy
obj.paid = !obj.paid;

// replace the array item with the new object
new_dataset[5] = obj;

Upvotes: 2

Shubham Khatri
Shubham Khatri

Reputation: 281656

Will React update all 5 rows or just the row holding the object I modified?

No it doesn't react render all the 5 rows again. Rather react optimises on a number of things to not render the same changes again. One such thing is a key attribute. Also React runs a diffing algorithm to render only the changes

Upvotes: 0

Giorgi Moniava
Giorgi Moniava

Reputation: 28654

Will React update all 5 rows or just the row holding the object I modified?

It will update only what has been changed. That is the purpose of reconciliation; I am not sure why you were looking for ways to avoid it. However, in your case you should use keys.

Upvotes: 2

Related Questions