Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
584 views
in Technique[技术] by (71.8m points)

javascript - 反应功能性无状态组件,PureComponent,Component; 有什么区别,什么时候应该使用什么?(React functional stateless component, PureComponent, Component; what are the differences and when should we use what?)

Came to know that from React v15.3.0 , we have a new base class called PureComponent to extend with PureRenderMixin built-in.

(从React v15.3.0开始 ,我们有了一个名为PureComponent的新基类,以扩展内置的PureRenderMixin 。)

What I understand is that, under the hood this employs a shallow comparison of props inside shouldComponentUpdate .

(我了解的是,在shouldComponentUpdate此方法对shouldComponentUpdate内部的道具进行了较浅的比较。)

Now we have 3 ways to define a React component:

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

  1. Functional stateless component which doesn't extend any class

    (功能性无状态组件,不扩展任何类)

  2. A component that extends PureComponent class

    (扩展PureComponent类的组件)

  3. A normal component that extends Component class

    (扩展Component类的常规组件)

Some time back we used to call stateless components as Pure Components, or even Dumb Components.

(一段时间以前,我们曾经将无状态组件称为“纯组件”,甚至称为“哑组件”。)

Seems like the whole definition of the word "pure" has now changed in React.

(似乎“纯”一词的整个定义现在已经在React中改变了。)

Although I understand basic differences between these three, I am still not sure when to choose what .

(尽管我了解这三者之间的基本区别,但仍不确定何时选择 。)

Also what are the performance impacts and trade-offs of each?

(另外,每种性能对性能有何影响和权衡?)


Update :(更新 :)

These are the question I expect to get clarified:

(这些是我希望得到澄清的问题:)

  • Should I choose to define my simple components as functional (for the sake of simplicity) or extend PureComponent class (for performance sake)?

    (我应该选择将我的简单组件定义为功能性的(出于简化的目的)还是扩展PureComponent类(出于性能的考虑)?)

  • Is the performance boost that I get a real trade-off for the simplicity I lost?

    (我为失去的简单性而获得了真正的性能提升吗?)

  • Would I ever need to extend the normal Component class when I can always use PureComponent for better performance?

    (当我始终可以使用PureComponent以获得更好的性能时,是否需要扩展普通的Component类?)

  ask by Yadhu Kiran translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

How do you decide, how do you choose between these three based on the purpose/size/props/behaviour of our components?(您如何决定,如何根据我们组件的目的/尺寸/道具/行为在这三个之间进行选择?)

Extending from React.PureComponent or from React.Component with a custom shouldComponentUpdate method have performance implications.

(使用自定义的shouldComponentUpdate方法从React.PureComponent或从React.Component扩展具有性能影响。)

Using stateless functional components is an "architectural" choice and doesn't have any performance benefits out of the box (yet).

(使用无状态功能组件是一种“架构”选择,并且没有任何现成的性能优势。)

  • For simple, presentational-only components that need to be easily reused, prefer stateless functional components.

    (对于需要易于重用的简单的仅表示组件,首选无状态功能组件。)

    This way you're sure they are decoupled from the actual app logic, that they are dead-easy to test and that they don't have unexpected side effects.

    (这样,您可以确定它们与实际的应用程序逻辑是分离的,它们非常易于测试,并且没有意外的副作用。)

    The exception is if for some reason you have a lot of them or if you really need to optimise their render method (as you can't define shouldComponentUpdate for a stateless functional component).

    (例外是如果出于某种原因有很多它们,或者确实需要优化它们的渲染方法(因为您无法为无状态功能组件定义shouldComponentUpdate )。)

  • Extend PureComponent if you know your output depends on simple props/state ("simple" meaning no nested data structures, as PureComponent performs a shallow compare) AND you need/can get some performance improvements.

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

  • Extend Component and implement your own shouldComponentUpdate if you need some performance gains by performing custom comparison logic between next/current props and state.

    (如果需要通过在下一个/当前道具与状态之间执行自定义比较逻辑来获得一些性能提升,则扩展Component并实现自己的shouldComponentUpdate 。)

    For example, you can quickly perform a deep comparison using lodash#isEqual:

    (例如,您可以使用lodash#isEqual快速执行深度比较:)

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

Also, implementing your own shouldComponentUpdate or extending from PureComponent are optimizations, and as usual you should start looking into that only if you have performance issues ( avoid premature optimizations ).

(此外,实现自己的shouldComponentUpdate或从PureComponent扩展都是优化,通常,只有在遇到性能问题时才应开始研究( 避免过早的优化 )。)

As a rule of thumb, I always try to do these optimisations after the application is in a working state, with most of the features already implemented.

(根据经验,我总是尝试在应用程序处于工作状态并且已经实现了大多数功能之后进行这些优化。)

It's a lot easier to focus on performance problems when they actually get in the way.

(当实际遇到问题时,专注于性能问题要容易得多。)

More details(更多细节)

Functional stateless components:

(功能性无状态组件:)

These are defined just using a function.

(这些仅使用函数定义。)

Since there's no internal state for a stateless component, the output (what's rendered) only depends on the props given as input to this function.

(由于无状态组件没有内部状态,因此输出(呈现的内容)仅取决于作为此函数的输入给出的props。)

Pros:

(优点:)

  • Simplest possible way of defining a component in React.

    (在React中定义组件的最简单的方法。)

    If you don't need to manage any state, why bother with classes and inheritance?

    (如果您不需要管理任何状态,为什么还要麻烦类和继承呢?)

    One of the main differences between a function and a class is that with the function you are sure the output depends only on the input (not on any history of the previous executions).

    (函数和类之间的主要区别之一是,使用函数可以确保输出仅取决于输入(而不取决于先前执行的任何历史记录)。)

  • Ideally in your app you should aim to have as many stateless components as possible, because that normally means you moved your logic outside of the view layer and moved it to something like redux, which means you can test your real logic without having to render anything (much easier to test, more reusable, etc.).

    (理想情况下,在您的应用中,您应该致力于拥有尽可能多的无状态组件,因为这通常意味着您将逻辑移到了视图层之外,然后将其移至了redux之类,这意味着您可以测试真实的逻辑而无需渲染任何内容(更容易测试,更可重用等)。)

Cons:

(缺点:)

  • No lifecycle methods.

    (没有生命周期方法。)

    You don't have a way to define componentDidMount and other friends.

    (您没有办法定义componentDidMount和其他朋友。)

    Normally you do that within a parent component higher in the hierarchy so you can turn all the children into stateless ones.

    (通常,您可以在层次结构中较高的父级组件中执行此操作,以便可以将所有子级变为无状态的子级。)

  • No way to manually control when a re-render is needed, since you can't define shouldComponentUpdate .

    (由于无法定义shouldComponentUpdate ,因此无法手动控制何时需要重新渲染。)

    A re-render happens every time the component receives new props (no way to shallow compare, etc.).

    (每当组件接收到新的道具时,就会进行重新渲染(无法进行浅比较等)。)

    In the future, React could automatically optimise stateless components, for now there's some libraries you can use.

    (将来,React可以自动优化无状态组件,因为现在可以使用一些库。)

    Since stateless components are just functions, basically it's the classic problem of "function memoization".

    (由于无状态组件只是函数,因此基本上是“函数记忆”的经典问题。)

  • Refs are not supported: https://github.com/facebook/react/issues/4936

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

A component that extends PureComponent class VS A normal component that extends Component class:

(扩展PureComponent类的组件VS扩展Component类的普通组件:)

React used to have a PureRenderMixin you could attach to a class defined using React.createClass syntax.

(React以前具有PureRenderMixin您可以将其附加到使用React.createClass语法定义的类。)

The mixin would simply define a shouldComponentUpdate performing a shallow comparison between the next props and the next state to check if anything there changed.

(mixin只需定义一个shouldComponentUpdate即可在下一个道具和下一个状态之间进行浅表比较,以检查是否有任何变化。)

If nothing changes, then there's no need to perform a re-render.

(如果没有任何变化,则无需执行重新渲染。)

If you want to use the ES6 syntax, you can't use mixins.

(如果要使用ES6语法,则不能使用mixins。)

So for convenience React introduced a PureComponent class you can inherit from instead of using Component .

(因此,为方便起见,React引入了您可以从其继承的PureComponent类,而不是使用Component 。)

PureComponent just implements shouldComponentUpdate in the same way of the PureRendererMixin .

(PureComponent只是以shouldComponentUpdate的相同方式实现了PureRendererMixin 。)

It's mostly a convenience thing so you don't have to implement it yourself, as a shallow comparison between current/next state and props is probably the most common scenario that can give you some quick performance wins.

(这主要是方便的事情,因此您不必自己实现,因为当前/下一个状态与道具之间的浅层比较可能是最常见的情况,可以使您快速获得性能。)

Example:

(例:)

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

As you can see the output depends on props.imageUrl and props.username .

(如您所见,输出取决于props.imageUrlprops.username 。)

If in a parent component you render <UserAvatar username="fabio" imageUrl="http://foo.com/fabio.jpg" /> with the same props, React would call render every time, even if the output would be exactly the same.

(如果在父组件中使用相同的道具渲染<UserAvatar username="fabio" imageUrl="http://foo.com/fabio.jpg" /> ,则即使输出完全相同,React也会每次调用render相同。)

Remember though that React implements dom diffing, so the DOM would not be actually updated.

(请记住,尽管React实现了dom diff,所以DOM实际上不会被更新。)

Still, performing the dom diffing can be expensive, so in this scenario it would be a waste.

(不过,执行dom diff可能会很昂贵,因此在这种情况下这将是浪费。)

If the UserAvatar component extends PureComponent instead, a shallow compare is performed.

(如果UserAvatar组件扩展了PureComponent ,则执行浅表比较。)

And because props and nextProps are the same, render will not be called at all.

(而且因为props和nextProps相同,所以将根本不会调用render 。)

Notes on the definition of "pure" in React:

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

In general, a "pure function" is a function that evaluates always to the same result given the same input.

(通常,“纯函数”是在给定相同输入的情况下始终对相同结果求值的函数。)

The output (for React, that's what is returned by the render method) doesn't depend on any history/state and it doesn't have any side-effects (operations that change the "world" outside of the function).

(输出(对于React,这是render方法返回的结果)不依赖于任何历史记录/状态,也没有任何副作用(在函数外部更改“世界”的操作)。)

In React, stateless components are not necessarily pure components according to the definition above if you call "stateless" a component that never calls this.setState and that doesn't use this.state .

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

In fact, in a PureComponent , you can still perform side-effects during lifecycle methods.

(实际上,在PureComponent ,您仍然可以在生命周期方法中执行副作用。)

For example you could send an ajax request inside componentDidMount or you could perform some DOM calculation to dynamically adjust the height of a div within render .

(例如,您可以在componentDidMount内发送ajax请求,或者可以执行一些DOM计算以动态调整render内div的高度。)

The "Dumb components" definition has a more "practical" meaning (at least in my understanding): a dumb component "gets told" what to do by a parent component via props, and doesn't know how to do things but uses props callbacks instead.

(“愚蠢的组件”定义具有更“实用”的含义(至少在我的理解中):一个愚蠢的组件“通过道具被告知”父组件要做什么,并且不知道该怎么做,而是使用道具回调。)

Example of a "smart" AvatarComponent :

(“智能” AvatarComponent


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...