【问题标题】:Will a stateless component re-render if its props have not changed?如果 props 没有改变,无状态组件会重新渲染吗?
【发布时间】:2018-03-26 00:10:21
【问题描述】:

我学到的关于 React 的一件事是,如果组件的 props 没有改变,那么 React 就不会费心重新渲染组件。无状态组件也是如此吗?还是它们的行为更像“愚蠢”的函数并且每次都被执行?

例如,如果我有:

import StatelessComponent from '../StatelessComponent';

export default class DocumentsTable extends React.Component {
  state = {
    something: 'foobar',
  };

  render() {
    return (
      <div>
        { this.state.something }
        <StatelessComponent theOnlyProp='baz'>
      </div>
    )
  }
};

this.state.something 更新其值时,&lt;StatelessComponent&gt; 是否会重新渲染?或者它是否足够“聪明”地看到它的 props 没有改变,就像其他 React 组件一样?

【问题讨论】:

    标签: reactjs


    【解决方案1】:

    2018 年 10 月 25 日更新

    从 React 16.6 开始,您可以将 React.memo 用于功能组件以防止重新渲染,类似于 PureComponent 用于类组件:

    const MyComponent = React.memo((props) => {
      return (
        /* markup */
      );
    });
    

    另外,备忘录也可以internal optimization

    与用户态 memo() 高阶组件实现不同,React 内置的组件可以通过避免额外的组件层来提高效率。 块引用


    旧答案

    是的,如果在组件本身或其其中之一中调用 setState(),它们总是会重新渲染 1(除非您使用 React.memo 如上所述)父母,因为功能性无状态组件不携带shouldComponentUpdate。事实上,每个 React 组件都会被重新渲染1,除非它们实现了shouldComponentUpdate


    需要注意的是,调用 render() 并不意味着 DOM 节点正在以任何方式被操纵render 方法只是服务于diff algorithm 来决定哪些 DOM 节点需要真正附加/分离。 请注意 render() 并不昂贵,昂贵的是 DOM 操作。它们仅在render() 返回不同的虚拟树时才会执行。

    来自 React 的 documentation

    需要明确的是,在这种情况下重新渲染意味着为所有组件调用渲染,这并不意味着 React 会卸载并重新安装它们。它只会应用遵循前几节所述规则的差异。

    别担心,除非你的组件很大,否则让 render() 被调用,那么你最好使用实现 shouldComponentUpdate() 的有状态组件。

    查看here 进行有趣的讨论。

    1 表示调用了组件的render() 函数,而不是正在操作底层的DOM 节点。

    【讨论】:

    • 感谢您提及.memo。这正是我所需要的。
    【解决方案2】:

    如果无状态组件的 props 没有改变,它会重新渲染吗?

    是的。 Stateless 渲染函数将被调用,即使没有任何变化。但是,React 会在协调阶段将虚拟 DOM(由渲染函数生成)与现有 DOM 进行比较。这在管道中还很遥远,因此如果渲染函数的计算成本很高,则不理想。

    纯组件确实有一个默认的属性浅比较,并且会停止要执行的渲染。将 Pure 组件 视为一个普通的 类 React 组件,它有一个 shouldComponentUpdate 与等于现有属性和新属性的三元组进行比较。

    话虽如此,您可以使用 Recompose.pure (https://github.com/acdlite/recompose/blob/master/docs/API.md#pure) 将您的 Stateless 组件 包装成一个 Pure 组件,它会自动执行,就像 纯组件,在不影响无状态组件的简短语法的情况下进行浅层比较。

    import StatelessComponent from '../StatelessComponent';   
    const PureChildFromStatelessComponent = Recompose.pure(StatelessComponent);
    // ... 
    <PureChildFromStatelessComponent ... />
    

    【讨论】:

      【解决方案3】:

      看到 react 不仅会重新渲染,如果 props 发生变化,它甚至会在任何状态发生变化时重新渲染自己。在您的情况下,组件将随着您的状态变化而重新呈现。 react 的工作方式是基于一种名为 Reconciliation 的算法,该算法的作用是将您的虚拟 DOM 与真实 DOM 进行比较,如果发现任何变化,则通过将其替换为您的虚拟 DOM,因此状态的任何变化都会导致整个组件的重新渲染。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-09-23
        • 1970-01-01
        • 2021-04-26
        • 2018-12-31
        • 1970-01-01
        • 1970-01-01
        • 2020-08-01
        相关资源
        最近更新 更多