React:更新self的最佳方式,但阻止孩子更新?

时间:2016-04-13 15:17:26

标签: javascript reactjs

我正在进行拖放式实现(从头开始,不使用DND库),并希望在拖动过程中限制不必要的更新次数。

拖动"克隆" (通常是原始元素的副本,但可以是任意占位符)是通过更新容器组件上的状态(" Clonetainer")并使用它来应用转换来实现的。但是,在移动过程中更新整个子树是没有意义的,因为唯一的变化是容器的坐标。

以下是我的解决方案:

const ClonetainerRenderShield = React.createClass({
    shouldComponentUpdate: function (newProps) {
        return newProps.shouldUpdate;
    },
    render: function () {
        return this.props.children; // Simple pass-through
    }
});

const Clonetainer = React.createClass({
    componentWillReceiveProps: function (newProps) {
        // OR in any further properties that may indicate a move, versus a child update
        this.isMoveEvent = this.props.offset !== newProps.offset;
    },
    render: function () {
        const style = { transform: `translate(${this.props.offset.left}px,${this.props.offset.top}px)` };
        return <div className="clonetainer-div" style={style}>
            <ClonetainerRenderShield shouldUpdate={ !this.isMoveEvent }>
                { this.props.children }
            </ClonetainerRenderShield>
        </div>;
    }
});

(我不会详细介绍其他DND系统的细节,只是说来自上游组件的鼠标事件将偏移参数提供给Clonetainer。)

我提出的用于停止更新的解决方案包括确定Clonetainer是否因为移动或其他原因而触发更新(并相应地设置this.isMoveEvent),然后填充Clonetainer和由基于传入道具(shouldUpdate)的shouldComponentUpdate组成的子项。

这很有效。我已经对它进行了测试,表明它应该在应该更新时进行更新而不应该更新,但是在那里只有一个单独的垫片组件感觉有点过头了。阻止更新流下山。是否有一种方法可以指示子组件不应该从render中的先前状态更新,而不需要子组件包含其自己的shouldComponentUpdate逻辑?

1 个答案:

答案 0 :(得分:1)

您应该可以在componentWillReceiveProps组件中将shouldComponentUpdate更改为Clonetainer并删除中间人。 shouldComponentUpdate有两个参数(object nextProps, object nextState),您可以使用这些参数再次比较this.statethis.props。返回true将导致重新渲染。

const Clonetainer = React.createClass({
    shouldComponentUpdate: function (nextProps, nextState) {
        // OR in any further properties that may indicate a move, versus a child update
        this.props.offset !== nextProps.offset;
    },
    render: function () {
        const style = { transform: `translate(${this.props.offset.left}px,${this.props.offset.top}px)` };
        return <div className="clonetainer-div" style={style}>
            { this.props.children }
        </div>;
    }
});