Constants props

Let's keep on improving our list example, and see what happens when we add new features.

In this case, we will learn how to avoid a common error when using PureComponent, which makes it less effective.

Suppose we want to add a prop to our Item component, which represents a list of statuses that the item can have. There are many ways of implementing it, but our focus is more on the way we pass down the default values.

Change the render method of the List component as follows:

  render() { 
return (
<div>
<ul>
{this.state.items.map(item => (
<Item
key={item}
item={item}
onClick={console.log}
statuses={['open', 'close']}
/>
))}
</ul>
<button onClick={this.handleClick}>+</button>
</div>
);
}

In the preceding code, for each Item, we set the key and the item prop to the current value of item. We fire console.log when the onClick event is fired inside Itemand we now have a new prop, which represents the possible statuses of item.

Now, if we render the List component inside the browser we see foo and bar as usual, and if we click the + button to add baz, we notice a new message in the console:

  Item.props.statuses
Value did not change. Avoidable re-render!
before ["open", "close"]
after ["open", "close"]

Item.props.statuses
Value did not change. Avoidable re-render!
before ["open", "close"]
after ["open", "close"]

The message is telling us that even if the values inside the array stay the same, on every render we are passing a new instance of the array to Item.

The reason behind this behavior is that all the objects return a new instance when created and a new array is never equal to another, even if they contain the same values:

  [] === [] 
false

There is also a table printed on the console, which shows the time that React is wasting rendering the items with unchanged props when there is no need to touch the DOM.

What we can do to solve the issue here is to create the array once, and always pass the same instance to every render:

  import React, { Component } from 'react';
import Item from './Item';

const statuses = ['open', 'close'];

class List extends Component {
constructor(props) {
super(props);

this.state = {
items: ['foo', 'bar']
};

this.handleClick = this.handleClick.bind(this);
}

handleClick() {
const items = this.state.items.slice();
items.unshift('baz');

this.setState({
items
});
}

render() {
return (
<div>
<ul>
{this.state.items.map(item => (
<Item
key={item}
item={item}
onClick={console.log}
statuses={statuses}
/>
))}
</ul>
<button onClick={this.handleClick}>+</button>
</div>
);
}
}

export default List;

If we try the component again in the browser, we see that the console now contains no message, which means that the items do not re-render themselves unnecessarily when the new element is added.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset