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.imageUrl
和props.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