Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React re render array whereas item key has not changed

Very basic code sample of a list:

class List extends React.Component {
    render() {
        const listComponent = this.props.numbers.map((number) =>
            <Item key={ number.toString() } value={ number } />,
        );

        return (
            <div>
                <button onClick={ () => this.setState({ test: 1 })}>Re-render list</button>
                { listComponent }
            </div>
        );
    }
}

An here is the item:

class Item extends React.Component {
    render() {
        return (
            <div>{ this.props.value + ', rendered time:' + new Date().getTime() }</div>
        );
    }
}

When I click the button, the state is updated so the List component is re-rendered.

However, if my understanding is correct, the items should not be re-rendered since the key item has not changed. But it does re-render since the timestamp is updated.

Can someone explain me why?

like image 574
vital Avatar asked Jul 28 '17 03:07

vital


2 Answers

Your understanding is completely wrong

The whole purpose of key, is for ordering rather than rendering. Image you have items a,b,c,d and reorder them by switch a and c, i.e. c,b,a,d. Without the key, it is extremely hard for react to figure out how to transform from the old virtual DOM to new virtual DOM.

Please read this https://facebook.github.io/react/docs/lists-and-keys.html

like image 78
Guichi Avatar answered Oct 01 '22 23:10

Guichi


By re-rendering a component you also start a chain reaction re-render on all the child components.

If you wish to prevent a child component to re-render (if some of the passed props didn't change for example) you can use the lifecycle method shouldComponentUpdate().

class Item extends React.Component {
    shouldComponentUpdate(nextProps) {
        // only re-render if props.value has changed
        return this.props.value !== nextProps.value;
    }

    render() {
        return (
            <div>{ this.props.value + ', rendered time:' + new Date().getTime() }</div>
        );
    }
}
like image 31
Tom Van Rompaey Avatar answered Oct 02 '22 00:10

Tom Van Rompaey