[解決済み】Reactの機能的なステートレスコンポーネント、PureComponent、Component、どのような違いがあり、いつ何を使うべきですか?
質問
から知ったのですが
リアクトv15.3.0
という新しいベースクラスがあります。
ピュアコンポーネント
で拡張し
ピュアレンダーミキシン
を組み込んでいます。私が理解しているのは、これはボンネットの中で
shouldComponentUpdate
.
これで、Reactコンポーネントを定義する方法が3つ揃いました。
- クラスを拡張しない機能的なステートレスコンポーネント
-
を拡張するコンポーネントです。
PureComponent
クラス -
を拡張した通常のコンポーネントです。
Component
クラス
少し前までは、ステートレス・コンポーネントのことをピュア・コンポーネント、あるいはダム・コンポーネントと呼んでいました。Reactでは、「純粋」という言葉の定義が変わったようです。
この3つの基本的な違いは理解していますが、まだよくわかりません。 いつ何を選択するか . また、それぞれのパフォーマンスへの影響やトレードオフはどのようなものでしょうか?
更新情報 :
これらの質問は、私が解明を期待しているものです。
-
シンプルなコンポーネントを機能的なものとして定義するか(シンプルにするため)、それとも
PureComponent
クラス(パフォーマンスのため)ですか? - を使用することで、パフォーマンスアップを実現することができます。 シンプルさが失われた?
-
を拡張する必要はありますか?
Component
クラスを使用することができます。PureComponent
を使えば、より良いパフォーマンスが得られるのでは?
解決方法は?
私たちの部品の目的/サイズ/小道具/動作に基づいて、この3つの中からどのように決めるか、どのように選ぶか?
からの拡張
React.PureComponent
または
React.Component
を使用し、カスタム
shouldComponentUpdate
メソッドは、パフォーマンスに影響を与えます。ステートレスな機能コンポーネントを使用することは、アーキテクチャ上の選択であり、(まだ)すぐにパフォーマンス上の利点が得られるわけではありません。
-
再利用が容易である必要がある、シンプルなプレゼンテーション専用のコンポーネントには、ステートレス関数型コンポーネントが適しています。こうすることで、実際のアプリのロジックから切り離され、テストが非常に簡単になり、予期せぬ副作用がないことを確認できます。例外は、何らかの理由で たくさん を定義することができないため)、レンダリングメソッドを最適化する必要がある場合です。
shouldComponentUpdate
は、ステートレスな関数型コンポーネントのためのものです。) -
エクステンド
PureComponent
出力が単純なpropやstateに依存することがわかっていて(PureComponentは浅い比較を行うので、ネストしたデータ構造がないことを意味します)、いくつかのパフォーマンス向上が必要/可能であれば。 -
拡張
Component
を実装し、独自のshouldComponentUpdate
もし、next/current props と state の間のカスタム比較ロジックを実行してパフォーマンスを向上させる必要がある場合。例えば、lodash#isEqualを使えば深い比較を素早く行うことができます。class MyComponent extends Component { shouldComponentUpdate (nextProps, nextState) { return !_.isEqual(this.props, nextProps) || !_.isEqual(this.state, nextState); } }
また、自分で実装した
shouldComponentUpdate
を拡張したものです。
PureComponent
は最適化であり、通常通り、パフォーマンスに問題がある場合にのみ検討を開始すべきです (
早すぎる最適化を避ける
).
経験則として、私はいつも、アプリケーションが動作する状態になり、ほとんどの機能がすでに実装された後で、これらの最適化を行うようにしています。パフォーマンスの問題は、実際に邪魔になったときに焦点を当てる方がずっと簡単だからです。
詳細
機能的なステートレス・コンポーネント。
これらは、単に関数を使って定義されています。ステートレス・コンポーネントは内部状態を持たないので、出力(レンダリングされるもの)はこの関数への入力として与えられたpropsにのみ依存します。
長所
-
Reactでコンポーネントを定義する最もシンプルな方法です。状態を管理する必要がないのであれば、なぜわざわざクラスや継承を使うのか?関数とクラスの主な違いは、関数では出力が入力にのみ依存することが確実なことです(以前の実行の履歴には依存しない)。
-
なぜなら、それは通常、ロジックをビューレイヤーの外に移動し、reduxのようなものに移動したことを意味するからです。つまり、何もレンダリングせずに実際のロジックをテストすることができます(より簡単にテストでき、より再利用できるなど)。
短所
-
ライフサイクルメソッドがない。を定義する方法がない
componentDidMount
といった仲間たちがいます。通常は、より高い階層の親コンポーネントの中でそれを行い、すべての子をステートレスにすることができます。 -
を定義できないので、再レンダリングが必要なときに手動で制御する方法がありません。
shouldComponentUpdate
. コンポーネントが新しいプロップを受け取るたびに、再レンダリングが発生します(浅い比較などを行う方法はありません)。将来的には、Reactはステートレスコンポーネントを自動的に最適化することができますが、現時点では、いくつかのライブラリを使用することができます。ステートレス・コンポーネントは単なる関数なので、基本的には "関数のメモ化" の古典的な問題です。 -
Refはサポートされていません。 https://github.com/facebook/react/issues/4936
PureComponent クラスを継承したコンポーネント VS Component クラスを継承した通常のコンポーネント。
Reactでは以前は
PureRenderMixin
を使用して定義されたクラスにアタッチすることができます。
React.createClass
の構文があります。ミキシンは単に
shouldComponentUpdate
は、次の props と次の状態を浅く比較し、そこで何かが変更されたかどうかをチェックすることを実行します。もし何も変更がなければ、再レンダリングを行う必要はありません。
ES6の構文を使いたい場合、mixinは使えません。そこで、Reactは利便性を高めるために
PureComponent
を使用する代わりに、継承することができます。
Component
.
PureComponent
を実装しているだけです。
shouldComponentUpdate
と同じように
PureRendererMixin
. 現在の状態/次の状態とpropsの浅い比較は、おそらく最も一般的なシナリオであり、いくつかの迅速なパフォーマンスの勝利を与えることができるので、これはほとんど便利なもので、自分でそれを実装する必要はありません。
例
class UserAvatar extends Component {
render() {
return <div><img src={this.props.imageUrl} /> {{ this.props.username }} </div>
}
}
ご覧の通り、出力は
props.imageUrl
と
props.username
. 親コンポーネントで次のようにレンダリングすると
<UserAvatar username="fabio" imageUrl="http://foo.com/fabio.jpg" />
を同じpropsで呼び出すと、Reactは
render
は毎回、たとえ出力がまったく同じであっても、です。しかし、Reactはdom diffingを実装しているので、DOMは実際には更新されないことを忘れないでください。それでも、dom diffing の実行にはコストがかかるので、このシナリオでは無駄になってしまいます。
もし
UserAvatar
コンポーネントが拡張する
PureComponent
の代わりに、浅い比較が実行されます。また、propsとnextPropsが同じであるため
render
は全く呼ばれない。
Reactにおける"pure"の定義に関する注意点。
一般に、quot;pure function"とは、同じ入力があれば常に同じ結果に評価される関数のことを指します。出力(Reactの場合、これは
render
メソッド) は履歴や状態に依存せず、副作用 (関数の外側で "world" を変更する操作) を持ちません。
Reactでは、ステートレス・コンポーネントは必ずしも上記の定義に従った純粋なコンポーネントではありません。
this.setState
を使用せず、かつ
this.state
.
実際には
PureComponent
を使用すると、ライフサイクルメソッド中に副作用を実行することができます。たとえば、次のような内部で ajax リクエストを送信できます。
componentDidMount
の中で、DOM 計算を行って div の高さを動的に調整することもできます。
render
.
Dumb components" の定義には、(少なくとも私の理解では)より実用的な意味があります。Dumb components "gets told" what to do by a parent component via props, and doesn't know how to do things but used props callbacks instead.
smart" の例。
AvatarComponent
:
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>
}
}
例:"dumb"
AvatarComponent
:
class AvatarComponent extends Component {
render () {
<div onClick={this.props.onExpandAvatar}>
{this.props.loading && <div className="spinner" />}
<img src={this.props.username} />
</div>
}
}
最終的には、「ダム」、「ステートレス」、「ピュア」はそれぞれまったく異なる概念であり、ユースケースによって重なる場合もありますが、必ずしもそうとは限りません。
関連
-
[解決済み】エラー。Ionic使用中にモジュール '../lib/utils/unsupported.js' が見つかりませんでした。
-
[解決済み] JavaScriptで "use strict "は何をするのか、その根拠は?
-
[解決済み] callとapplyの違いは何ですか?
-
[解決済み] JavaScriptで二重引用符と単一引用符はいつ使うべきですか?
-
[解決済み] Bowerとnpmの違いは何ですか?
-
[解決済み] varキーワードの目的と、どのような場合に使用する(または省略する)べきですか?
-
[解決済み] Node.jsのmodule.exportsの目的と使い方を教えてください。
-
[解決済み] ES6インポートで中括弧を使用するのはどのような場合ですか?
-
[解決済み] React NativeとReactの違いは何ですか?
-
[解決済み] TypeScriptでReactのステートレス機能コンポーネントを使用して子供を使用する方法?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
jsを使った簡単な照明スイッチのコード
-
vueのグローバルがscss(mixin)を導入。
-
vueが定義するプライベートフィルタと基本的な使い方
-
[解決済み】React - uncaught TypeError: 未定義のプロパティ 'setState' を読み取れない
-
[解決済み】SyntaxError: JSONの位置1に予期しないトークンoがある。
-
[解決済み】JavaScriptの配列でforEachが関数でない不具合
-
HTML5 LocalStorage ローカルストレージとセッションストレージの使用法
-
モジュールのビルドに失敗しました。Error: ENOENT: no such file or directory, scandir 'D:\.... \node_modules
-
jq は html ページとデータを動的に分割する。
-
[解決済み】React.ComponentとReact.PureComponentの比較【終了しました