当React Element作为Prop传递时,防止重新渲染

时间:2016-06-06 19:28:32

标签: reactjs material-ui react-intl

在我的React应用程序中,我使用了一些库(即Material UI和React Intl)将React元素作为道具从更高级别的组件传递到具有一个作业的“哑组件”:渲染。

智能组件:

import ActionExplore from 'material-ui/svg-icons/action/explore';
import { FormattedMessage } from 'react-intl';

export class SmartComponent extends Component {
  render() {
    return (
      <div>
        <DumbComponent
          text={<FormattedMessage id="en.dumbComponent.text" />}
          icon={<ActionExplore/>}
        />
        <AnotherDumbComponent {props.that.are.changing} />
      </div>
    );
  }
}

哑组件:

import shallowCompare from 'react-addons-shallow-compare';

export class DumbComponent extends Component {
  shouldComponentUpdate(nextProps, nextState) {
    return shallowCompare(this, nextProps, nextState);
  }

  render() {
    return (
      <div>
        <h1>{this.props.text}</h1>
        {this.props.icon}
      </div>
    );
  }
}

这样做的好处是,DumbComponent不需要了解任何有关应用程序逻辑(材料ui,国际化等)的知识。它只是呈现,让SmartComponent处理所有业务逻辑。

我遇到这种方法的缺点是性能:DumbComponent将总是重新渲染,即使AnotherDumbComponent的道具改变而不是它自己的道具,因为shouldComponentUpdate 总是返回trueshouldComponentUpdate无法在上例中的React元素之间进行准确的等式检查。

如何在shouldComponentUpdate中对React元素进行相等检查?执行成本太高了吗?将React元素作为道具传递给哑组件是一个坏主意吗?是否有可能将传递给React元素作为道具,但保持组件愚蠢?谢谢!

2 个答案:

答案 0 :(得分:0)

是否具有高性能将取决于您的用例。根据经验,我认为当你期望用户输入只影响“哑组件”的孩子而不是它的同伴时,最好使用这种逻辑。

例如,Material-UI的Dialog与你的动作按钮和标题的建议几乎相同。 (https://github.com/callemall/material-ui/blob/master/src/Dialog/Dialog.js#L292)。但是在这种情况下效果很好,因为这些元素在模态上,除非你打开或关闭它,否则它本身不会修改。

作为另一种潜在的解决方法,如果传入创建子元素所需的对象而不传入整个元素,该怎么办?我没试过这个,所以我不确定它会有多好用,但值得一试。达到某种程度;

<DumbComponent 
    textComponent={FormattedMessage} 
    textProps={{id: "en.dumbComponent.text"}}/>

//In DumbComponent;

render(){
    return (
        <div>
            <h1>
                <this.props.textComponent {...this.props.textProps}/>
            </h1>

        </div>
    );
}

在确定是否应该更新时,可能会给你一些更具体的事情。

答案 1 :(得分:0)

我通过将这些简单的React元素转换为Immutable.js地图并将它们作为道具传递来解决这个问题。

这篇文章非常有用:https://www.toptal.com/react/react-redux-and-immutablejs

  

Immutable.js允许我们检测JavaScript对象/数组中的更改,而不会诉诸深度相等检查的低效率,这反过来允许React避免在不需要时进行昂贵的重新呈现操作。