React state array updates/renders entire array, is there a work-around?
Asked Answered
G

1

6

Here's the basic idea...

constructor(props) {
    super(props);
    this.state = {
        children: [{id:1},{id:2}], // HERE ARE THE TWO OBJECTS
        style: {top: 0}
    };
}

Now let's say I update one of those two objects but those objects are mapped to an array of components.

<div className="thread">
    {this.state.children.map((child) =>
        <Post
            key={child.id}
            id={child.id}
        />
    )}
</div>

Now... when I update one of those objects...

changeID (id, newID) { // this is a different function, just an example
    let temp = this.state.children;
    for (let i = 0; i < temp.length; i++) {
        if (temp[i].id === id) {
            temp[i].id = newID; // <- update this
        }
    }
    this.setState({
        children: temp // <- plug temp[] back as the updated state
    });
}

I throw the new state back in, but it updates each of the mapped objects.

// on one change to one element
id 1 POST UPDATED
id 2 POST UPDATED

1) Does it re-render EVERY component (in the mapped array) or is it smart enough to tell that the state values passed as props to the mapped component are the same?

2) Is it incredibly expensive in processing power if that array is significantly longer?

3) If yes, how can I go about this better? Constructive criticism is appreciated.

Thank you!

Goldeye answered 29/6, 2017 at 10:19 Comment(2)
how you know it is updating the each object?Oleate
@MayankShukla componentDidUpdate(){console.log("UPDATED");}Goldeye
O
9

This is how react works, whenever you change any state variable it will re-render the complete component and update the virtual dom not the actual dom, then it will check the diff between these two and change only that particular element in actual dom.

As per DOC:

React provides a declarative API so that you don't have to worry about exactly what changes on every update.

React Only Updates What's Necessary:

React DOM compares the element and its children to the previous one, and only applies the DOM updates necessary to bring the DOM to the desired state.

DOM Elements Of The Same Type:

When comparing two React DOM elements of the same type, React looks at the attributes of both, keeps the same underlying DOM node, and only updates the changed attributes.

For Example:

<div className="before" title="stuff" />

<div className="after" title="stuff" />

By comparing these two elements, React knows to only modify the className on the underlying DOM node.

Use of Keys:

React supports a key attribute. When children have keys, React uses the key to match children in the original tree with children in the subsequent tree.

Imp:

Keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside the array to give the elements a stable identity. Keys used within arrays should be unique among their siblings. However they don't need to be globally unique.

For example:

<ul>
  <li key="2015">Duke</li>
  <li key="2016">Villanova</li>
</ul>

<ul>
  <li key="2014">Connecticut</li>
  <li key="2015">Duke</li>
  <li key="2016">Villanova</li>
</ul>

Now React knows that the element with key '2014' is the new one, and the elements with the keys '2015' and '2016' have just moved.

Check this article: How Virtual-DOM and diffing works in React

Oleate answered 29/6, 2017 at 10:36 Comment(2)
Wow what a fantastic response. So, I'm aware the Virtual-DOM maintains the actual DOM and compares (fantastic article), but the children of the container component each call the componentDidUpdate() method. Does that method name mean something different than I think it means? The webpage/components don't seem to refresh everything when I update a state so I think you've hit the nail on the head.Goldeye
@JohnCullen glad, it helped you :)Oleate

© 2022 - 2024 — McMap. All rights reserved.