ES6クラスベースのReactコンポーネントと機能的なES6 Reactコンポーネントをいつ使用するのですか?


212

Reactの学習に少し時間を費やした後、コンポーネント作成の2つの主要なパラダイムの違いを理解しました。

私の質問は、いつどちらを使用する必要があるのか​​、そしてその理由は何ですか?一方の利点ともう一方の利点は何ですか?


ES6クラス:

import React, { Component } from 'react';

export class MyComponent extends Component {
  render() {
    return (
      <div></div>
    );
  }
}

機能的:

const MyComponent = (props) => {
    return (
      <div></div>
    );
}

そのコンポーネントによって操作される状態がないときはいつでも機能的だと思いますが、それはそれですか?

ライフサイクルメソッドを使用する場合は、クラスベースのコンポーネントを使用するのが最善だと思います。


7
あなたはすでに答えを知っているようです。
Felix Kling 2016年

2
renderメソッドのみのコンポーネントがある場合、それを機能的な形式に変えることができます。ステートレスレンダー機能以上のものが必要な場合は、クラスを使用してください
just-boris

2
もっと簡潔にするためには、これを試してください:const MyComponent = (props) => <div>...</div>
Viliam Simko

1
回避できる場合は、機能を使用しません。私は必然的に将来的にクラスベースのリファクタリングが必要になるからです。そして、その後、しばしば機能的にリファクタリングする必要があります。
keithjgrant

2020年の正しいアプローチは、可能な限り機能コンポーネントを使用することです。これは、コンポーネントがフックをサポートし、フックが(パフォーマンス的にもアーキテクチャ的にも)代替手段よりも優れているためです。
polkovnikov.ph

回答:


161

あなたは正しい考えを持っています。コンポーネントがいくつかの小道具を取り込んでレンダリングする以外に機能しない場合は、機能を使用してください。これらは、同じ小道具が与えられた場合、常に同じようにレンダリングおよび動作するため、これらを純粋な関数と考えることができます。また、ライフサイクルメソッドを気にしないか、独自の内部状態を持っています。

これらは軽量であるため、これらの単純なコンポーネントを機能コンポーネントとして作成することはかなり標準的です。

状態を保持するなど、コンポーネントにさらに機能が必要な場合は、代わりにクラスを使用してください。

詳細:https : //facebook.github.io/react/docs/reusable-components.html#es6-classes


編集:上記のほとんどは、React Hooksが導入されるまでは真実でした。

  • componentDidUpdateで複製できますuseEffect(fn)fnは、再レンダリング時に実行される関数です。

  • componentDidMountメソッドはを使用して複製できますuseEffect(fn, [])。ここで、fnは再レンダリング時に実行する関数[]であり、コンポーネントが再レンダリングするオブジェクトの配列です(少なくとも1つが前回のレンダリング以降に値を変更した場合のみ)。何もないので、useEffect()最初のマウントで1回実行されます。

  • stateで複製できますuseState()。その戻り値は、状態の参照と状態を設定できる関数(つまり、const [state, setState] = useState(initState))に分解できます。例はこれをより明確に説明するかもしれません:

const Counter = () => {
  const [count, setCount] = useState(0)

  const increment = () => { 
    setCount(count + 1);
  }

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>+</button>
    </div>
  )
}

default export Counter

機能コンポーネントよりもクラスを使用する場合の推奨事項に関して、Facebookは可能な限り機能コンポーネントを使用すること正式に推奨しています。余談ですが、パフォーマンス上の理由から機能コンポーネントを使用しないことについて多くの人々が議論していると聞きました。

「イベント処理関数は、機能コンポーネントのレンダリングごとに再定義されます」

確かに、コンポーネントが本当に懸念されるような速度またはボリュームでレンダリングしているかどうかを検討してください。

そうであればuseCallbackuseMemoフックを使用して関数を再定義することを防ぐことができます。ただし、これによりコードが(微視的に)パフォーマンスが低下する可能性があることに注意してください。

しかし正直なところ、Reactアプリで関数を再定義することがボトルネックになるとは聞いたことがありません。時期尚早の最適化はすべての悪の根源です-それが問題であるとき、これを心配してください


状態を保持しないが、コンポーネントに密​​接に結合されている機能についてはどうでしょうか。たとえば、レンダリングの動的属性を決定します。
デニス

これにより、コンポーネントの2種類の違いについての最もよい記事で反応です:code.tutsplus.com/tutorials/...
牡羊座生まれのアコスタ

5
React 16.8では、useStateフックを介して機能コンポーネントで状態を使用できます。
グレッグ

React 16.8では、機能コンポーネントでほぼすべてを実行でき、すべての効果を最終的にモジュール化して、パフォーマンスへの影響を最小限に抑えることができます。
polkovnikov.ph

1
どこで情報を見つけましたFacebook officially recommends using functional components wherever possibleか?
johannchopin

40

可能な限り、常にステートレス関数(機能コンポーネント)の使用を試みてください。通常のReactクラスを使用する必要があるシナリオがあります。

  • コンポーネントは状態を維持する必要があります
  • コンポーネントの再レンダリングが多すぎます。それを介して制御する必要があります shouldComponentUpdate
  • コンテナコンポーネントが必要です

更新

浅い小道具の比較を処理する独自のクラスを実装PureComponentする(の代わりにComponent)拡張可能なReactクラスがありshouldComponentUpdateます。続きを読む


43
Always try to use stateless functions (functional components) whenever possible.私はそれを言う10人を読みました。それでもその理由を説明する者はいなかった。
Rotareti

25
In an ideal world, most of your components would be stateless functions because in the future we’ll also be able to make performance optimizations specific to these components by avoiding unnecessary checks and memory allocations. This is the recommended pattern, when possible.さらに詳しい情報:facebook.github.io/react/docs/...
ディオゴカルドーゾ

2
@rotaretiあなたがあなたの質問に答えてもらえたと感じるかどうかはわかりませんが、純粋な関数は理解、テスト、保守がはるかに簡単です。同じパラメーターを指定すると、それらは常に同じものをレンダリングします。ライフサイクルイベントが発生したときに状態を維持して変化するコンポーネントは、理解するのが困難です。必ずしも必要ではないことは言うまでもありませんが、それらの利点が必要ない場合は、不要な定型文とオーバーヘッドを追加するだけでメリットがないことは明らかです。
door_number_three

独自のイベントハンドラー定義がある場合は、Componentクラスを作成することもできます。これにより、すべてのレンダリングで新しい関数を作成する代わりに、コンストラクターのコンポーネントにそれらのイベントハンドラーを事前にバインドできます。すべてのイベントハンドラーが小道具からのものである場合、これは必要ありません。
Dobes Vandermeer 2017

引用されたFacebookの推奨事項が存在しないことに注意してください(上記の私のコメントを参照)。
ギャレット

34

2019年3月の更新

https://overreacted.io/how-are-function-components-different-from-classes/

2019年2月の更新:

Reactフックの導入により、Reactチームは可能な限り機能コンポーネントを使用することを望んでいるように見えます(JavaScriptの機能的性質によく従う)。

彼らの動機:

1.) Its hard to reuse stateful logic between components
2.) Complex components become hard to understand
3.) Classes confuse both people and machines

フックを備えた機能コンポーネントは、クラスコンポーネントが実行できるほとんどすべてのことを実行できます。

できるだけ早く使用することをお勧めします。

元の回答

機能コンポーネントは、クラスベースのコンポーネントほど軽量ではなく、「クラスとまったく同じように機能します」。- https://github.com/facebook/react/issues/5677#issuecomment-241190513

上記のリンクは少し古くなっていますが、React 16.7.0のドキュメントには、機能コンポーネントとクラスコンポーネントが次のように記載されています。

「Reactの観点からは同等です。」- https://reactjs.org/docs/components-and-props.html#stateless-functions

構文を除いて、機能コンポーネントと、renderメソッドを実装するだけのクラスコンポーネントとの間に本質的に違いはありません。

将来(上記のリンクを引用)、「私たち[React]はそのような最適化を追加する可能性があります。」

不要なレンダリングを排除してパフォーマンスを向上させようとしている場合は、どちらの方法でもサポートが提供されます。memo機能コンポーネントおよびPureComponentクラス用。

- https://reactjs.org/docs/react-api.html#reactmemo

- https://reactjs.org/docs/react-api.html#reactpurecomponent

それはあなた次第です。ボイラープレートを少なくしたい場合は、機能します。関数型プログラミングが好きで、クラスが気に入らない場合は、関数型にしてください。コードベースのすべてのコンポーネント間の一貫性が必要な場合は、クラスを使用してください。のようなものが必要なときに機能ベースのコンポーネントからクラスベースのコンポーネントにリファクタリングするのにうんざりしている場合は、クラスを使用してくださいstate


1
すべてのコンポーネントをReact.Componentで拡張すると、コードが読みやすくなります(特に新しい人にとって)。毎回同じ方法で作成されたコンポーネントを見るといいです。@Galupufが言ったように、単純なコンポーネントには「render()」と呼ばれるメソッドが1つだけあります。「this」のバインドを開始したり、状態を保持したりする場合など、すべてをリファクタリングする必要がなく、必要なものを追加することができるため、すべてをReact.Componentに拡張するのも良い方法です。
jeffski13 2018

10

React 16.8の時点で、ステートレス機能コンポーネントという用語は誤解を招くものであり、もはやステートレスではない(React.SFCは非推奨React.SFCのDan Abramov)ので、状態を持つことができ、フックを持つことができます(これは、ライフサイクルメソッド)も同様に、クラスコンポーネントと多少重複しています

クラスベースのコンポーネント

機能コンポーネント:

機能部品を好む理由

  • ReactはcomponentDidMountcomponentDidUpdatecomponentWillUnmountライフサイクルメソッドを組み合わせるための非常に明確で簡潔な方法であるuseEffectフックを提供します
  • フックを使用すると、コンポーネント間で簡単に共有でき、テスト可能なロジックを抽出できます
  • スコーピングに関する混乱が少ない

フック(つまり、機能コンポーネント)を使用する理由についての動機を反応させます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.