ホームページ >ウェブフロントエンド >jsチュートリアル >ステートレスコンポーネントを使用した反応性能を最適化します
呼び出しは含まれておらず、「小道具」と子コンポーネントを着信する処理のみが処理されます。 this.state = { ... }
キーポイントの概要
概要
this.state = { … }
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>
コードは正常に実行されます。それは非常に基本的ですが、例を構築します。
注意する必要があります:
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
this
user
救助のために再構成!
最初に、目標を確認しましょう:
ドキュメントによると、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>プロップが変更された場合にのみ更新されることに気付くでしょう。親コンポーネントが再レンダリングされている場合、ユーザーコンポーネントは再レンダリングしません。
ディスカッションname
highlighted
最初に、コンポーネントのパフォーマンスを最適化する価値があるかどうかを自問してください。たぶんそれはそれだけの価値があります。コンポーネントは軽量である必要があります。高価な計算をコンポーネントから移動して外部の記憶に残る関数に移動するか、コンポーネントを再編成して、使用時にコンポーネントをレンダリングすることを無駄にしないようにコンポーネントを再編成できます。たとえば、この例では、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
を知り、実現することはまだ良いことです。 recompose.onlyUpdateForKeys
Reactの詳細については、「ES6 Way」というコースをご覧ください。
この記事は、ジャック・フランクリンによって査読されました。 SetePointのコンテンツを完璧にしてくれたすべてのSitePoint Peer Revenyersに感謝します!
ステートレスコンポーネントを使用した反応性能の最適化に関するよくある質問ステートフルコンポーネントとReactのステートレスコンポーネントの主な違いは何ですか?
状態コンポーネント(クラスコンポーネントとも呼ばれます)は、時間の経過とともにコンポーネント状態の変化に関するメモリを維持します。彼らは、コンポーネントがどのように振る舞い、レンダリングするかについて責任を負います。一方、ステートレスコンポーネント(機能コンポーネントとも呼ばれます)には、独自の状態がありません。彼らは親コンポーネントから小道具の形でデータを受け取り、それをレンダリングします。それらは主にコンポーネントのUI部分に責任があります。ステートレスコンポーネントは、Reactアプリケーションのパフォーマンスを大幅に改善できます。独自の状態またはライフサイクルの方法を管理していないため、コードが少ないため、理解してテストしやすくなります。また、アプリケーションによって消費されるメモリの量を減らすこともできます。パフォーマンスを最適化するために、状態コンポーネントを可能な限りステートレスコンポーネントに変換し、Reactの
PureComponent
は、アプリケーションのパフォーマンスを最適化するのに役立つ特別なReactコンポーネントです。浅い小道具と状態の比較を使用して、shouldComponentUpdate
ライフサイクル法を実装します。これは、状態または小道具が変更された場合にのみ再レンダリングされることを意味します。これにより、不必要な再レンダリングを大幅に削減し、パフォーマンスを改善できます。
//ステータスコンポーネント クラスのようこそruce.componentを拡張する{ 与える() { return
hello、{this.props.name}
hello、{props.name}
ステートレスコンポーネントは、Reactでライフサイクルメソッドを使用できますか?
反応におけるステートレスコンポーネントの制限は何ですか?
ステートレスコンポーネントはどのようにしてコードの読みやすさを改善できますか?
ステートレスコンポーネントは反応のイベントを処理できますか?
関数actionlink(props){ 戻る (
私をクリックしてください ); }
ステートレスコンポーネントは、コードのモジュール化をどのように促進しますか?以上がステートレスコンポーネントを使用した反応性能を最適化しますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。