4

在我的 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 的 props 改变而不是它自己的,因为shouldComponentUpdate 总是返回trueshouldComponentUpdate在上面的示例中,无法在 React 元素之间进行准确的相等性检查。

如何对 React 元素进行相等检查shouldComponentUpdate?这是否太昂贵而无法执行?将 React 元素作为道具传递给哑组件是一个坏主意吗?是否可以将 React 元素作为道具传递,但让组件保持哑巴?谢谢!

4

2 回答 2

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>
    );
}

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

于 2016-06-06T20:25:26.897 回答
-1

我通过将这些普通的 React 元素转换为 Immutable.js 映射,并将它们作为道具传递来解决了这个问题。

这篇文章很有帮助:https ://www.toptal.com/react/react-redux-and-immutablejs

Immutable.js 允许我们检测 JavaScript 对象/数组的变化,而无需求助于深度相等检查的低效率,这反过来又允许 React 在不需要时避免昂贵的重新渲染操作。

于 2016-06-07T16:59:37.740 回答