beauchette
beauchette

Reputation: 1126

Refresh only the component that changed from the parent

I have a react component that is a list, let's call it List, it has a state named items that is an array of object of the form :

{ id: String, name: String }

its render function is something like

render () {
    return (
        <ul>
          { items.map((item) => {
            return (
              <Item key={item.id} item={item} />
            );
          })}
        </ul>
    );
}

with Item being a react component too, of course.

So now, my question: let's say that at one point, I know that the data changed (it can only be a name change, of course), how can I trigger Item to refresh based on its key from the parent?

I found two solutions so far :

  1. refreshing the whole state, but I don't like it cause it seems overkill.
  2. maintaining an array of references to the child components, but I don't like it cause it feels like a waste of memory.

so what's a 'reactier' way of doing this?

Upvotes: 3

Views: 6851

Answers (3)

Simon
Simon

Reputation: 490

By implementing shouldComponentUpdate(nextProps, newState) in your React components you can calculate whether or not the component needs to update. So if you send a whole new object in, this should trigger already in its default implementation (they don't do a deep-compare), but if the property input.name is changed then it will not detect this. So you could implement this yourself like this:

shouldComponentUpdate(nextProps, newState) {
    return this.props.name === nextProps.name; // use === to compare types too!
}

Now I'm a bit rusty on the JavaScript (I prefer TypeScript), so I am not sure if this is the correct way to compare strings.

Upvotes: 1

Vorcan
Vorcan

Reputation: 116

Using the shouldComponentUpdate() method, you can specify whether or not a component should update based on the current props and the new props which are provided as:

shouldComponentUpdate(nextProps){
    return this.props.item.name !== nextProps.item.name; 
}

Here's a JsFiddle with a demo: https://jsfiddle.net/Vorcan/Lakj6qwb/

Usually, you have to create a new object instance using something like Object.assign().

Other than the docs, another good resource to check out shouldComponentUpdate is https://developmentarc.gitbooks.io/react-indepth/content/life_cycle/update/using_should_component_update.html

Upvotes: 0

Shubham Khatri
Shubham Khatri

Reputation: 281696

If the items array changed then the render of the Parent is called, since the keys Item components are same, the component is not re-created but its componentWillReceiveProps function is called and the Item component is re-rendered.

What you can do as an optimization is to create a Item component as a Pure component which you can do by extending React.PureComponent. React.PureComponent’s shouldComponentUpdate() only shallowly compares the objects so if the Props haven't changed a rerender on child is not called.

According to the DOCS:

If your React component’s render() function renders the same result given the same props and state, you can use React.PureComponent for a performance boost in some cases.

React.PureComponent’s shouldComponentUpdate() only shallowly compares the objects. If these contain complex data structures, it may produce false-negatives for deeper differences. Only extend PureComponent when you expect to have simple props and state, or use forceUpdate() when you know deep data structures have changed. Or, consider using immutable objects to facilitate fast comparisons of nested data.

Furthermore, React.PureComponent’s shouldComponentUpdate() skips prop updates for the whole component subtree. Make sure all the children components are also “pure”.

Upvotes: 3

Related Questions