React.js:shouldComponentUpdate在无状态子组件数组中

React.js: shouldComponentUpdate in array of stateless child Components

本文关键字:组件 数组 状态 js shouldComponentUpdate React      更新时间:2023-09-26

我有一个父React类(<EventList />),它包含一个存储其子组件(<Event />)数据的对象。为了简洁起见,我省略了许多函数。

EventList的现状背景

/**
 * The events state looks like this before the EventList component is rendered:
 *
 * var events = {
 *      1: {
 *          id: 1,
 *          title: "Some title"
 *      },
 *      2: {
 *          id: 2,
 *          title: "Some other title"
 *      },
 *
 *      ...
 * };
 */

事件.jsx

var Event = React.createClass({
    /**
     * Pass up the ID of the Event and the new value of the Event's Title
     */
    _handleChange: function (e) {
        this.props.handleChange(this.props.id, e.target.value);
    },
    render: function () {
        return (
            <div className="event">
                <input type="text" value={this.props.title} onChange={this._handleChange} />
            </div>
        );
    }
});

事件列表.jsx

var EventList = React.createClass({
    propTypes: {
        events: React.PropTypes.object
    },

    /**
     * Update the State of an event who's title has changed
     */
    _handleChange: function (id, title) {
        var newState = React.addons.update(this.state.events[id].title, {
            $set: title
        });
        this.setState(newState);
    },
    render: function () {
        var renderedEvents = Object.keys(this.state.events).map(function (id) {
            var event = this.state.events[id];
            return <Event key={event.id} title={event.title} handleChange={this._handleChange}/>;
        }, this);
        return (
            <div className="events">
                {renderedEvents}
            </div>
        );
    }
});

现在这很好,而且有效。标题的状态会得到更新,所有内容都会成功渲染和重新渲染;但这也是问题所在:

一切都重新渲染

列表中有几个事件也不错,但一旦有大量事件,当EventList渲染函数通过并填充<Event />组件的新阵列时,重新渲染会带来巨大的性能损失。

我希望能够做的一件事(尽管假设这需要对应用程序进行完整的重组)是能够在<Event />组件中使用shouldComponentUpdate

然而,以我目前的关系,我不能这样做。如果您查看shouldComponentUpdate:的默认参数

shouldComponentUpdate: function(nextProps, nextState) {...},

您会注意到,在<Event />级别上,this.props将始终等于nextProps,因此尝试执行以下操作:

shouldComponentUpdate: function(nextProps, nextState) {
    return this.props !== nextProps; 
},

将始终返回CCD_ 12,因为在事物流的这一点上,它们指向完全相同的数据集。CCD_ 13当然不存在于CCD_。

因此,我的问题是,我需要做些什么来摆脱<EventList />级别上极其昂贵的重新渲染?

问题出在您的更新调用中。目前,您基本上执行var newState = title。您需要实际更新顶级状态密钥。

_handleChange: function (id, title) {
    var update = {};
    update[id] = {title: {$set: title}};
    var newEvents = React.addons.update(this.state.events, update);
    this.setState({events: newEvents});
},

或者使用ES6,您可以避免本地变量:

_handleChange: function (id, title) {
    var newEvents = React.addons.update(this.state.events, {
        [id]: {
            title: {$set: title}
        }
    });
    this.setState({events: newEvents});
},