当前位置: 首页 > 知识库问答 >
问题:

反应功能无状态组件、PureComponent、component;区别是什么?我们应该在什么时候使用什么?

倪培
2023-03-14

了解到,从React v15.3.0中,我们有一个名为PureComponent的新基类,可以使用PureRenderMixin内置进行扩展。我所理解的是,在引擎盖下,它采用了应该组件更新内部道具的浅层比较。

现在我们有3种方法来定义React组件:

  1. 不扩展任何类的函数无状态组件
  2. 扩展PureComponent
  3. 的组件
  4. 扩展Component
  5. 的普通组件

一段时间以前,我们将无状态组件称为纯组件,甚至是哑组件。似乎“纯粹”这个词的整个定义现在在《反应》中已经改变了。

虽然我理解这三者之间的基本区别,但我仍然不确定什么时候选择什么。另外,每种方法的性能影响和权衡是什么?

以下是我希望澄清的问题:

  • 我应该选择将我的简单组件定义为功能组件(为了简单)还是扩展PureComponent类(为了性能)?
  • 我失去的简单性是否真的让我得到了性能提升?
  • 当我可以始终使用PureComponent以获得更好的性能时,我是否需要扩展普通的组件

共有3个答案

淳于烈
2023-03-14

>

  • React.Component是默认的“正常”组件。您可以使用关键字和扩展React.Component声明它们。将它们视为一个类,包含生命周期方法、事件处理程序和任何方法。

    React.PureComponent是一个React.Component组件,它实现了shouldComponentUpdate(),并使用一个函数对其道具状态进行粗略比较。如果知道组件具有已更改的道具或状态嵌套数据,并且要重新渲染,则必须使用forceUpdate()。因此,当作为道具传递或设置在状态中的阵列或对象发生变化时,如果需要组件重新渲染,它们就不太好了。

    功能组件是没有生命周期功能的组件。它们被认为是无状态的,但是它们非常好而且干净,我们现在有了钩子(从React 16.8开始),所以您仍然可以拥有一个状态。所以我猜它们只是“干净的组件”。

  • 弓磊
    2023-03-14

    我不是一个反应过度的天才,但根据我的理解,我们可以在以下情况下使用每个组件

    >

    纯组件-这些是具有生命周期的项目,当给定一组特定的道具时,它们总是返回相同的结果。这些组件可以在显示结果列表或特定对象数据时使用,这些数据没有复杂的子元素,并且用于执行仅影响其自身的操作用户可以执行点击查看详情页或添加到购物车。

    普通组件或复杂组件——我使用术语复杂组件,因为它们通常是页面级组件,由许多子组件组成,而且每个子组件都可以以其独特的方式运行,因此您不能100%确定它在给定状态下会呈现相同的结果。正如我所说,通常这些应该用作容器组件

    乔鸿骞
    2023-03-14

    React扩展。PureComponent或从React.具有自定义的Component应该具有性能影响。使用无状态功能组件是一种“架构”选择,目前还没有任何开箱即用的性能优势。

    >

  • 对于需要轻松重用的简单、仅表示性的组件,首选无状态函数组件。通过这种方式,您可以确保它们与实际的应用程序逻辑解耦,它们非常容易测试,并且没有意外的副作用。例外情况是,如果出于某种原因,您有很多这样的组件,或者您真的需要优化它们的呈现方法(因为您不能为无状态函数组件定义应该组件更新)。

    扩展PureComponent,如果您知道您的输出依赖于简单的道具/状态(“简单”意味着没有嵌套的数据结构,因为PureComponent执行的是浅层比较),并且您需要/可以获得一些性能改进。

    如果您需要通过执行下一个/当前道具和状态之间的自定义比较逻辑来提高性能,请扩展Component并实现您自己的应该ComponentUpdate。例如,您可以快速执行深度比较,使用lodash#is相等:

    class MyComponent extends Component {
        shouldComponentUpdate (nextProps, nextState) {
            return !_.isEqual(this.props, nextProps) || !_.isEqual(this.state, nextState);
        }
    }
    

    此外,实现您自己的shouldComponentUpdate或从PureComponent扩展都是优化,通常只有在出现性能问题时才应该开始研究这一点(避免过早优化)。根据经验,我总是尝试在应用程序处于工作状态后进行这些优化,大多数功能已经实现。当性能问题真正成为阻碍时,更容易关注它们。

    功能无状态组件:

    这些都是使用函数定义的。由于无状态组件没有内部状态,因此输出(呈现的内容)仅取决于作为此函数输入的道具。

    赞成的意见:

    >

    理想情况下,在您的应用程序中,您应该尽可能多地使用无状态组件,因为这通常意味着您将逻辑移到了视图层之外,并将其移到了类似redux的位置,这意味着您可以在不必渲染任何内容的情况下测试真正的逻辑(更易于测试,更易于重用,等等)。

    欺骗:

    >

    没有办法手动控制何时需要重新渲染,因为您不能定义应该组件更新。每次组件收到新道具时都会发生重新渲染(无法进行浅层比较等)。)。将来,React可以自动优化无状态组件,现在有一些库可以使用。由于无状态组件只是函数,基本上这是“函数记忆”的经典问题。

    不支持引用:https://github.com/facebook/react/issues/4936

    扩展PureComponent类的组件与扩展组件类的普通组件相比:

    React过去有一个PureRenderMixin可以附加到使用React.createClass语法定义的类。mixin只需定义一个shouldComponentUpdate,在下一个道具和下一个状态之间执行一个粗略的比较,以检查是否有任何变化。如果没有任何更改,则无需执行重新渲染。

    如果你想使用ES6语法,你不能使用混合。为了方便起见,React引入了一个PureComponent类,您可以继承它,而不是使用Component。这主要是一件方便的事情,所以你不必自己实现它,因为当前/下一个状态和道具之间的浅层比较可能是最常见的场景,可以给你一些快速的性能胜利。

    例子:

    class UserAvatar extends Component {
        render() {
           return <div><img src={this.props.imageUrl} /> {{ this.props.username }} </div>
        }
    } 
    

    如您所见,输出取决于props.imageUrlprops.username。如果在父组件中渲染

    如果UserAvatar组件扩展了PureComponent,则执行浅层比较。而且因为props和nextProps是相同的,所以根本不会调用渲染

    关于React中“纯”定义的注释:

    一般来说,“纯函数”是指在给定相同输入的情况下,其计算结果总是相同的函数。输出(对于React,这是render方法返回的内容)不依赖于任何历史/状态,也没有任何副作用(改变函数外部“世界”的操作)。

    在React中,如果您将“无状态”组件称为从不调用this.setState且不使用this.state的组件,则根据上述定义,无状态组件不一定是纯组件。

    事实上,在PureComponent中,您仍然可以在生命周期方法期间执行副作用。例如,您可以在componentDidMount中发送一个ajax请求,或者执行一些DOM计算来动态调整render中div的高度。

    “Dumb components”的定义有一个更“实际”的含义(至少在我的理解中):一个Dumb component通过props被父组件“告知”要做什么,并且不知道如何做,而是使用props回调。

    “智能”化身组件的示例:

    class AvatarComponent extends Component {
        expandAvatar () {
            this.setState({ loading: true });
            sendAjaxRequest(...).then(() => {
                this.setState({ loading: false });
            });
        }        
    
        render () {
            <div onClick={this.expandAvatar}>
                <img src={this.props.username} />
            </div>
        }
    }
    

    “哑”化身组件的示例:

    class AvatarComponent extends Component {
        render () {
            <div onClick={this.props.onExpandAvatar}>
                {this.props.loading && <div className="spinner" />}
                <img src={this.props.username} />
            </div>
        }
    }
    

    最后,我要说的是,“哑”、“无状态”和“纯”是完全不同的概念,有时可以重叠,但不一定重叠,这主要取决于您的用例。

  •  类似资料:
    • 问题内容: 从 React v15.3.0 知道,我们有了一个名为 PureComponent 的新基类,以扩展内置的 PureRenderMixin 。我了解的是,在幕后,它对内部的道具进行了浅浅的比较。 现在,我们有3种方法来定义React组件: 功能性无状态组件,不扩展任何类 扩展类的组件 扩展类的常规组件 一段时间以前,我们曾经将无状态组件称为“纯组件”,甚至称为“哑组件”。似乎“纯”一词

    • 问题内容: 我正在使用’multiprocess.Pool.imap_unordered’如下 我需要打电话或之后的for循环? 问题答案: 不,您没有,但是如果您不再使用游泳池,那可能是个好主意。 Tim Peters在此SO帖子中致电或致电的理由很明确: 至于Pool.close(),您应该在永远不会将更多工作提交给Pool实例的情况下(且仅在)进行调用。因此,通常在主程序的可并行化部分完成时

    • 问题内容: 我知道他们两个都禁用了Nagle的算法。 我什么时候应该/不应该使用它们中的每一个? 问题答案: 首先,不是所有人都禁用Nagle的算法。 Nagle的算法用于减少有线中更多的小型网络数据包。该算法是:如果数据小于限制(通常是MSS),请等待直到收到先前发送的数据包的ACK,同时累积用户的数据。然后发送累积的数据。 这将对telnet等应用程序有所帮​​助。但是,在发送流数据时,等待A

    • 问题内容: 在该类中,有两个字符串,和。 有什么不同?我什么时候应该使用另一个? 问题答案: 如果你的意思是和则: 用于在文件路径列表中分隔各个文件路径。考虑在上的环境变量。您使用a分隔文件路径,因此在上将是;。 是或用于拆分到特定文件的路径。例如在上,或

    • 最近,我收到了在代码中使用's的建议,或者在站点上看到了一些使用's的答案--应该是某种容器。但是--我在C++17标准库里找不到类似的东西。 那么这个神秘的是什么?如果它是非标准的,为什么(或何时)使用它是个好主意?

    • 问题内容: 面试官问我: 什么是Observer,什么Observable时候应该使用它们? 我并不了解这些术语,因此当我回到家并开始使用GoogleObserver和Google搜索时Observable,从不同的资源中发现了一些要点: 1)Observable是一个类,Observer是一个接口。 2)Observable该类维护一个Observers的列表。 3)当一个Observable对