ホームページ >ウェブフロントエンド >jsチュートリアル >ステートレスコンポーネントを使用した反応性能を最適化します

ステートレスコンポーネントを使用した反応性能を最適化します

Lisa Kudrow
Lisa Kudrowオリジナル
2025-02-16 11:35:08326ブラウズ

Optimizing React Performance with Stateless Components

Optimizing React Performance with Stateless Components

この記事では、Reactのステートレスコンポーネントを調査します。このタイプのコンポーネントには、

呼び出しは含まれておらず、「小道具」と子コンポーネントを着信する処理のみが処理されます。 this.state = { ... } キーポイントの概要

概要

    Reactのステートレスコンポーネントには、
  • 呼び出しが含まれていません。着信の「小道具」とサブコンポーネントのみを処理するため、テストの観点からよりシンプルで分析しやすくなります。 this.state = { … }
  • ステートレスコンポーネントは、純粋なJavaScriptに似ており、使用されるフレームワークへの依存度が低い機能コンポーネントに変換できます。
  • ステートレスコンポーネントのパフォーマンスは、React.purecomponentを使用して最適化できます。これには、各Propの浅い比較を可能にする組み込み
  • メソッドがあります。 shouldComponentUpdate
  • Recomposeは、反応の関数コンポーネントと高度なコンポーネントのユーティリティライブラリです。プロップが変更されていない場合、再レンダリングせずに機能コンポーネントをレンダリングするために使用できます。
  • ステートレスコンポーネントは、独自の状態またはライフサイクルの方法を管理していないため、コードボリュームとメモリ消費を削減するため、Reactアプリケーションのパフォーマンスを大幅に改善できます。ただし、ライフサイクル方法を使用できない、自分の状態を管理できないなど、いくつかの制限があります。

基本

<code class="language-javascript">import React, { Component } from 'react'

class User extends Component {
  render() {
    const { name, highlighted, userSelected } = this.props
    console.log('Hey User is being rendered for', [name, highlighted])
    return <div>
      <h3 style="{{fontStyle:" highlighted : onclick="{event"> {
           userSelected()
         }}>
        {name}
      </h3>
    </div>
  }
}</code>

コードは正常に実行されます。それは非常に基本的ですが、例を構築します。

注意する必要があります:

  • なしで無国籍です。 this.state = { ... }
  • は、その使用法を理解するために使用されます。特に、パフォーマンスの最適化を実行する場合、プロップが実際に変更されていない場合、不必要な再レンダリングを避ける必要があります。 console.log
  • ここのイベントハンドラーは「インライン」です。この構文は、コードが処理する要素に近いため便利です。この構文は、何もする必要がないことを意味します
  • .bind(this) このようなインライン関数を使用すると、関数がレンダリングされるたびに作成する必要があるため、パフォーマンスが低くなります。これについては後で詳しく説明します。
コンポーネントを表示

上記のコンポーネントは無国籍であるだけでなく、実際にはダンアブラモフがディスプレイコンポーネントと呼んでいることを認識しています。それは単なる名前ですが、基本的には軽量で、HTML/DOMを生成し、状態データを処理しません。

それで、それを機能にすることができます!これは「クール」を感じるだけでなく、理解しやすいので恐ろしくなります。入力を受け取り、環境とは無関係に、常に同じ出力を返します。もちろん、小道具の1つが呼ばれる機能であるため、「コールバック」です。

書き直してみましょう:

<code class="language-javascript">import React, { Component } from 'react'

class User extends Component {
  render() {
    const { name, highlighted, userSelected } = this.props
    console.log('Hey User is being rendered for', [name, highlighted])
    return <div>
      <h3 style="{{fontStyle:" highlighted : onclick="{event"> {
           userSelected()
         }}>
        {name}
      </h3>
    </div>
  }
}</code>

気分がいいですよね?それは純粋なJavaScriptのように感じます。あなたが使用しているフレームワークについて考えずにそれを書くことができます。

継続的な再レンダリングの問題

ユーザーコンポーネントが、時間の経過とともに状態を変えるコンポーネントで使用されていると仮定します。しかし、状態は当社のコンポーネントに影響しません。たとえば、このように:

<code class="language-javascript">const User = ({ name, highlighted, userSelected }) => {
  console.log('Hey User is being rendered for', [name, highlighted])
  return <div>
    <h3 style="{{fontStyle:" highlighted : onclick="{event"> {
         userSelected()
       }}>
      {name}
    </h3>
  </div>
}</code>

このコードを実行すると、何も変更されていなくても、コンポーネントが再レンダリングされることに気付くでしょう!これは今では大きな問題ではありませんが、実際のアプリケーションでは、コンポーネントはますます複雑になる傾向があり、すべての不必要な再レンダリングにより、Webサイトが遅くなります。

このアプリケーションをデバッグしてreact-addons-perfを使用している場合、レンダリングUsers->Userで時間が無駄になっていると確信しています。おっと!何をするか? !

すべてが、shouldComponentUpdateを使用して、Reactがプロップが異なると思う方法をカバーする必要があることを示しているようであり、それらは違いはないと確信しています。 React Lifecycleフックを追加するには、コンポーネントがクラスである必要があります。 alas 。そこで、元のクラスベースの実装に戻り、新しいライフサイクルフック方法を追加します:

クラスコンポーネントに戻る

<code class="language-javascript">import React, { Component } from 'react'

class Users extends Component {
  constructor(props) {
    super(props)
    this.state = {
      otherData: null,
      users: [{name: 'John Doe', highlighted: false}]
    }
  }

  async componentDidMount() {
    try {
      let response = await fetch('https://api.github.com')
      let data = await response.json()
      this.setState({otherData: data})
    } catch(err) {
      throw err
    }
  }

  toggleUserHighlight(user) {
    this.setState(prevState => ({
      users: prevState.users.map(u => {
        if (u.name === user.name) {
          u.highlighted = !u.highlighted
        }
        return u
      })
    }))
  }

  render() {
    return <div>
      <h1>Users</h1>
      {
        this.state.users.map(user => {
          return <user name="{user.name}" highlighted="{user.highlighted}" userselected="{()"> {
              this.toggleUserHighlight(user)
            }}/>
         })
      }
    </user>
</div>
  }
}</code>

新しく追加されたshouldComponentUpdateメソッドに注意してください。これは少し醜いです。機能を使用できなくなるだけでなく、変更される可能性のあるプロップを手動でリストする必要があります。これには、userSelected関数プロップが変更されないという大胆な仮定が含まれます。これはありそうもないが、注意が必要だ。

しかし、含まれているアプリコンポーネントが再レンダリングされていても、これは一度だけレンダリングされることに注意してください!したがって、これはパフォーマンスに適しています。しかし、私たちはより良くすることができますか?

race.purecomponent

反応15.3以来、新しいコンポーネントベースクラスがあります。それはPureComponentと呼ばれ、各小道具の「浅い比較」を行う組み込みshouldComponentUpdateメソッドがあります。素晴らしい!これを使用すると、特定の小道具をリストする必要があるカスタムshouldComponentUpdateメソッドを破棄できます。

<code class="language-javascript">import React, { Component } from 'react'

class User extends Component {
  render() {
    const { name, highlighted, userSelected } = this.props
    console.log('Hey User is being rendered for', [name, highlighted])
    return <div>
      <h3 style="{{fontStyle:" highlighted : onclick="{event"> {
           userSelected()
         }}>
        {name}
      </h3>
    </div>
  }
}</code>

試してみると、あなたは失望するでしょう。毎回再レンダーします。なぜ? !答えは、アプリのuserSelectedメソッドで毎回render関数が再現されるためです。これは、PureComponentベースのコンポーネントが独自のshouldComponentUpdate()を呼び出す場合、関数が常に異なるため、trueを返すことを意味します。

通常、この問題の解決策は、コンポーネントを含むコンストラクターに関数を結合することです。まず、これを行う場合、メソッド名を5回(および1つ前)と入力する必要があることを意味します。

  • (コンストラクターで)this.userSelected = this.userSelected.bind(this)
  • (メソッド定義自体として)userSelected() { ... }
  • (ユーザーコンポーネントのレンダリングが定義されている場合)<user ... userselected="{this.userSelected}"></user>
別の問題は、ご覧のとおり、

メソッドが実際に実行されると、閉鎖に依存することです。特に、ITERATORのスコープ変数userSelectedに依存しています。 this.state.users.map() 確かに、この問題には解決策があります。これは、最初にuserメソッドを

に結合し、次にメソッドが(子コンポーネントで)呼び出されたら、

(またはその名前を渡すことです。 )戻って。これがこのような解決策です。 userSelected thisuser救助のために再構成!

最初に、目標を確認しましょう:

  1. 機能コンポーネントの書き込みは、機能であるため、気分が良くなります。これは、コードリーダーに、いかなる状態も救わないことを伝えます。彼らは単体テストの観点から簡単に推論することができます。そして、彼らはより簡潔で、より純粋なJavaScript(そしてもちろんJSX)のように感じます。
  2. 私たちは、子どものコンポーネントに渡されたすべての方法をバインドするにはあまりにも怠惰です。もちろん、メソッドが複雑な場合は、動的に作成する代わりにリファクタリングする方が良いでしょう。動的な作成方法により、コードを使用している場所で直接書き込むことができます。名前を付ける必要はありません。また、3つの異なる場所で5回言及することもできません。
  3. サブコンポーネントは、小道具が変更された場合にのみ再レンダリングする必要があります。これは、小規模で高速なコンポーネントには関係ないかもしれませんが、実用的なアプリケーションでは、これらのコンポーネントの多くがある場合、これらの追加のレンダリングはすべてを回避できればCPUを無駄にします。
(実際、私たちの理想的な状況は、コンポーネントが一度だけレンダリングされることです。なぜこの問題を解決できないのですか?その場合、「反応する方法をより速くする方法」のブログ投稿は90%削減されます。)

ドキュメントによると、Recomposeは「関数コンポーネントと高度なコンポーネント用のReactユーティリティツールのライブラリです。それをReactのロダッシュと考えてください。」

。このライブラリにはたくさんの探索がありますが、プロップが変更されていない場合は再レンダリングせずに機能コンポーネントをレンダリングしたいと考えています。 初めてrecompose.pureを使用して関数コンポーネントに書き戻しようとしたときは、次のようになります。

<code class="language-javascript">import React, { Component } from 'react'

class User extends Component {
  render() {
    const { name, highlighted, userSelected } = this.props
    console.log('Hey User is being rendered for', [name, highlighted])
    return <div>
      <h3 style="{{fontStyle:" highlighted : onclick="{event"> {
           userSelected()
         }}>
        {name}
      </h3>
    </div>
  }
}</code>

このコードを実行している場合、プロップ(キー)が変更されていなくても、ユーザーコンポーネントが再レンダリングされていることに気付く場合があります。

さらに一歩進めましょう。 nameは使用していませんが、highlightedを使用します。

recompose.pure recompose.onlyUpdateForKeys recompose.pure このコードを実行した後、

または
<code class="language-javascript">const User = ({ name, highlighted, userSelected }) => {
  console.log('Hey User is being rendered for', [name, highlighted])
  return <div>
    <h3 style="{{fontStyle:" highlighted : onclick="{event"> {
         userSelected()
       }}>
      {name}
    </h3>
  </div>
}</code>
プロップが変更された場合にのみ更新されることに気付くでしょう。親コンポーネントが再レンダリングされている場合、ユーザーコンポーネントは再レンダリングしません。

ディスカッションnamehighlighted

最初に、コンポーネントのパフォーマンスを最適化する価値があるかどうかを自問してください。たぶんそれはそれだけの価値があります。コンポーネントは軽量である必要があります。高価な計算をコンポーネントから移動して外部の記憶に残る関数に移動するか、コンポーネントを再編成して、使用時にコンポーネントをレンダリングすることを無駄にしないようにコンポーネントを再編成できます。たとえば、この例では、Fetchが完了する前にユーザーコンポーネントをレンダリングしたくない場合があります。

コードを最も便利な方法で作成し、プログラムを開始し、パフォーマンスを向上させるために繰り返すことは悪い解決策ではありません。この例では、パフォーマンスを改善するには、次のような関数コンポーネントを定義する必要があります。

<code class="language-javascript">import React, { Component } from 'react'

class User extends Component {
  render() {
    const { name, highlighted, userSelected } = this.props
    console.log('Hey User is being rendered for', [name, highlighted])
    return <div>
      <h3 style="{{fontStyle:" highlighted : onclick="{event"> {
           userSelected()
         }}>
        {name}
      </h3>
    </div>
  }
}</code>
……

に変更しました

理想的には、問題をバイパスする方法を示すのではなく、最良の解決策はReactからの新しいパッチであり、これが
<code class="language-javascript">const User = ({ name, highlighted, userSelected }) => {
  console.log('Hey User is being rendered for', [name, highlighted])
  return <div>
    <h3 style="{{fontStyle:" highlighted : onclick="{event"> {
         userSelected()
       }}>
      {name}
    </h3>
  </div>
}</code>
>

を「自動的に」識別して比較することが関数であり、単に大きな改善をもたらします。平等ではないということは、実際に異なるという意味ではありません。 shallowEqual

同意します!コンストラクターと各レクリエーションにメソッドを結合するインライン関数に対処しなければならないことに代わる妥協案があります。それがパブリッククラスの分野です。これはバベルのフェーズ2の機能であるため、セットアップがサポートされる可能性があります。たとえば、以下にそれを使用するブランチがあります。これは短いだけでなく、すべての機能以外の小道具を手動でリストする必要がないことを意味します。このソリューションは閉鎖を放棄する必要があります。それにもかかわらず、必要に応じて

を知り、実現することはまだ良いことです。 recompose.onlyUpdateForKeys

Reactの詳細については、「ES6 Way」というコースをご覧ください。

この記事は、ジャック・フランクリンによって査読されました。 SetePointのコンテンツを完璧にしてくれたすべてのSitePoint Peer Revenyersに感謝します!

ステートレスコンポーネントを使用した反応性能の最適化に関するよくある質問ステートフルコンポーネントとReactのステートレスコンポーネントの主な違いは何ですか?

状態コンポーネント(クラスコンポーネントとも呼ばれます)は、時間の経過とともにコンポーネント状態の変化に関するメモリを維持します。彼らは、コンポーネントがどのように振る舞い、レンダリングするかについて責任を負います。一方、ステートレスコンポーネント(機能コンポーネントとも呼ばれます)には、独自の状態がありません。彼らは親コンポーネントから小道具の形でデータを受け取り、それをレンダリングします。それらは主にコンポーネントのUI部分に責任があります。

ステートレスコンポーネントを使用してReactアプリケーションのパフォーマンスを最適化する方法は?

ステートレスコンポーネントは、Reactアプリケーションのパフォーマンスを大幅に改善できます。独自の状態またはライフサイクルの方法を管理していないため、コードが少ないため、理解してテストしやすくなります。また、アプリケーションによって消費されるメモリの量を減らすこともできます。パフォーマンスを最適化するために、状態コンポーネントを可能な限りステートレスコンポーネントに変換し、Reactの

を使用して、不必要な再レンダリングを避けることができます。

Purecomponentとは何ですか?また、React Performanceの最適化にどのように役立ちますか?

PureComponentは、アプリケーションのパフォーマンスを最適化するのに役立つ特別なReactコンポーネントです。浅い小道具と状態の比較を使用して、shouldComponentUpdateライフサイクル法を実装します。これは、状態または小道具が変更された場合にのみ再レンダリングされることを意味します。これにより、不必要な再レンダリングを大幅に削減し、パフォーマンスを改善できます。

ステートレスコンポーネントに反応する状態コンポーネントを変換する方法は?

状態コンポーネントをステートレスコンポーネントに変換することには、コンポーネントから状態またはライフサイクルメソッドの削除が含まれます。コンポーネントは、プロップを通じてデータを受信して​​レンダリングする必要があります。例は次のとおりです。

//ステータスコンポーネント クラスのようこそruce.componentを拡張する{ 与える() { return

hello、{this.props.name}

; } }
//ステートレスコンポーネント 機能歓迎(小道具){ return

hello、{props.name}

; }
反応でステートレスコンポーネントを使用するためのベストプラクティスは何ですか?

Reactのステートレスコンポーネントを使用するためのいくつかのベストプラクティスは、パフォーマンスと読みやすさを改善し、単一の機能を避けます。また、小道具分解を使用してクリーナーコードを書き込むこともお勧めします。

ステートレスコンポーネントは、Reactでライフサイクルメソッドを使用できますか?

いいえ、ステートレスコンポーネントはReactでライフサイクルメソッドを使用できません。ライフサイクル方法は、クラスコンポーネントにのみ適用できます。ただし、React 16.8にフックが導入されると、機能コンポーネントに状態とライフサイクルの機能を追加できるようになりました。

反応におけるステートレスコンポーネントの制限は何ですか?

ステートレスコンポーネントには多くの利点がありますが、いくつかの制限もあります。ライフサイクルの方法を使用したり、独自の状態を管理したりすることはできません。ただし、これらの制限は、Reactフックを使用することで克服できます。

ステートレスコンポーネントはどのようにしてコードの読みやすさを改善できますか?

ステートレスコンポーネントは、シンプルさと明確さを通じてコードの読みやすさを向上させます。彼らは自分の状態を管理したり、ライフサイクルの方法を使用したりしないため、よりシンプルで理解しやすくなります。また、小型の再利用可能なコンポーネントの使用を奨励しているため、コードがより整理され、メンテナンスが容易になります。

ステートレスコンポーネントは反応のイベントを処理できますか?

はい、ステートレスコンポーネントはReactのイベントを処理できます。イベントハンドラーは、プロップとしてステートレスコンポーネントに合格できます。例は次のとおりです。

関数actionlink(props){ 戻る (

私をクリックしてください ); }

ステートレスコンポーネントは、コードのモジュール化をどのように促進しますか?

ステートレスコンポーネントは、小規模で再利用可能なコンポーネントの使用を促進することにより、コードのモジュール化を促進します。各コンポーネントは独立して開発およびテストすることができ、コードの維持と理解が容易になります。また、各コンポーネントが単一の機能に責任を負う懸念の分離も促進します。

以上がステートレスコンポーネントを使用した反応性能を最適化しますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。