2

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.

3 Answers 3

2

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;
Sign up to request clarification or add additional context in comments.

7 Comments

Right. So based on this: reactjs.org/docs/…, shouldComponentUpdate will by default return true since I updated the state with a new object and then React will check each of the child objects where SCU will again return true (since they are all different objects now I guess) however vDOMEq will return true only for object with id 5 which is what React will actually re-render. Is that correct?
@kstratis yes and no. React will first update because setState() was called. Period. It doesn't yet know what's been updated/changed. Running setState() updates the state variables and then render() is executed. This mean that your whole map() will run also. Once render() is finished, the virtualDOM is updated and React will now check the differences between the new vDOM and the old vDOM. That's where it will see that only item 5 of your array is different and only that (real) DOM-node will be updated.
@kstratis Point is, if you have a large array, mapping it in the render() method might impact performance. It's important to understand that the "diffing" will happen after render() because React cannot magically forsee what's going to change in your DOM-tree - it doesn't know your application logic.
No, not really. You would only technically save the time it takes to copy an object which is negligible. I would still go with your approach, because it makes more sense to keep a collection of similar items in an array.
@kstratis you should look into key property anyway
|
2

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.

Comments

0

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

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.