Reputation: 8042
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
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
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
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