イオン反応アプリの貸し手の数を減らす方法


こんにちは、友人!
私はイオン反応でルーティングのための迅速なヒントを回避する計画を、この最初の記事へようこそ.
このシリーズをオフにするために、私は私が得る一番上の質問の1つに答えるつもりです
まず、複数の貸し手に過度に関心を持つべきではありません.レンダリングフェーズの間、反応はあなたのコンポーネントの表現を仮想DOMと呼びます.このvdomを構築するのは比較的安い.その後、VDOMは実際のDOMにあるものにVDOMを比較します.そして、実際の変更があるならば、それは高価なDOMアップデートをするだけです.
これは、あなたのコンポーネントが再びレンダリングされるが、変更がない場合、コストが最小であることを意味します.
しかし、レンダリングにはいくつかの欠点があります.最初に、反応はVDOMを構築しなければならなくて、各々のレンダリング呼び出しのためにそのDiffingアルゴリズムを実行しなければなりません.これは非常に最適化され、高速化されていますが、コンポーネントを更新する必要がない場合は無駄です.次に、Renderメソッドで高価なコードがある場合は、毎回実行されます.
また、私のような場合は、それはあなたのボンカーを駆動することができます.
したがって、貸し手の数を削減しようとすると、マイクロの最適化ですが、時々それは取る価値がある.
この記事では、なぜレンダリングが複数回呼び出されるのかを見てみましょう.次に、あなた自身のアプリケーションでそれらを減らすのに役立ついくつかのテクニックを紹介します.

プロジェクト設定


場合は、新しいイオン反応アプリを使用してIonic CLI :
ionic start RenderTest tabs --type=react 
とtab 1にある.TSXファイルは、関数の内部にログ文を追加します.
const Tab1: React.FC = () => {
  console.log('tab1 render');

  return (
    <IonPage>
      {...}
    </IonPage>
  );
};
火災のアプリをionic serve , そして、初期ロードでは、タブ1ページが2回レンダリングされます.

しかし、タブをクリックすると、タブを切り替えるたびに、タブ1を3 - 4回レンダリングすることがわかります!何が起こっているのですか.

なぜあなたはそんなにレンダリング?



イオン反応アプリ内のすべてのページはIonPage コンポーネント.IniPageはあなたのページとスタイルを保持するためのいくつかのDIVコンテナを提供するだけでなく、ページ遷移を行うことに関しても非常に重要です.
これらのイオンページへのリファレンスを取得するためにバックグラウンドで進行するいくつかの半複雑なロジックがあります.残念なことに、リファレンスを取得するには、コンポーネントがマウントされるまで待機する必要があります.これはすべてIronRouveContractコンポーネントで起こりますが、このコンポーネントがレンダリングされるとき、それはしばしばその子(ルートとイオンページ)をそれに沿ってレンダリングする原因となります.
これは、イオンのページが表示されるときに2回または3回、それが初めて表示される理由です.
次に、いくつかのページが現在のビューにないときにレンダリングされる可能性があることに注意してください.
滑らかなトランジションのいくつかを提供し、あなたが残したビューの状態を維持するために戻ってくるかもしれないようにするために、いくつかのシナリオ(タブ間を移動するような)で実際にコンポーネントをアンマウントしません.その代わりに、あなたのページが見えないとき、私たちはCSSを通してそれを隠します.コンポーネントはまだマウントされ、まだレンダリングできます.したがって、コンポーネントがそれに渡された新しい小道具を取得すると、それはレンダリングされます.
デフォルトでは、ルートは、次のようにルートのコンポーネントプロップであなたのイオノページを通過するセットアップです.
<Route path="/tab1" component={Tab1} exact={true} />
コンポーネントのプロップを使用する場合、Router Routerはあなたの代わりにいくつかの小道具を渡しますlocation and history . あなたがナビゲーションの変更を行うたびに、これらのルート小道具は、再度レンダリングするためにマウントされているすべてのイオンページを引き起こす変更されます.
これは手のビットを得ることができますので、いくつかの戦略を見てみましょう過度の貸し手を削減する.

貸し手の最適化


だからここに2つの主要な犯人があります.レンダリングされる親コンポーネントは、子プロセスをレンダリングし、新しいプロップを別のレンダリングを行うルーティングを渡します.
親コンポーネントを最初にレンダリングします.

コンポーネント


反応するクラスベースのコンポーネントでは、コンポーネントがshouldComponentUpdate ライフサイクル法.このメソッドは、新しい小道具/状態を受け取ります.そして、我々は古い小道具/州と比較することができて、我々が我々のコンポーネントがそのRenderメソッドを呼ぶかどうか決定することができました.または、さらに良い、我々はReact.PureComponent そして、反応を我々にとってこの論理の世話をさせてください.
これはあなたのコンポーネントがその小道具または状態が変わるならば更新するだけであるようにします、そして、親コンポーネントレンダリングからどんなアップデートも無視します.
反応機能的なコンポーネント(FC)で類似した何かを成し遂げるために、我々は2009年にFCを包むことができますReact.memo , どちらがmemoize コンポーネントに格納されている小道具に基づいてキャッシュされたバージョンを格納します.
そうするために、私はFCをラップしているReact.memo 以下のように:
export default React.memo(Tab1);
あなたは今、タブの間を移動するときにレンダリングの数はかなりビットカットされることに注意する必要があります.
使用React.memo あなたが基本的にメモリ消費のためにより少ない貸手を取引しているように、しかし、不必要な貸し手を減らす良い方法はこれをするとき、気をつけます.

ルート設定


次に、RouteルータがルートコンポーネントのプロップでもはやTab 1ページに渡さないように、ルートを変更しましょう.
ルート設定では、component プロップ、および反応ルータは、ナビゲーションの変更があるたびにすべてのルートの小道具を渡します.
反応ルータ5.1のように、ルートがいつマッチするかについて、どのコンポーネントを表示するかを指定する新しい方法があります.and this method is encouraged going forward .
新しい方法は、次のようにコンポーネントを子としてパスに渡すことです.
<Route path="/tab1" exact={true}>
  <Tab1 />
</Route>
さて、ログをチェックすると、Tab1 ページは最初のロード時に一度だけレンダリングされ、タブの間を移動するときに追加のレンダリングが行われません.ニース🎉!
「でも、コンポーネントのルーティング小道具が必要なのか?」聞いてね.
Router Routerはあなたが同様にそこでカバーしました.いくつかの新しいReact Hooks available 前に渡されたのと同じ小道具へのアクセスを得るために使用することができます.useParams , useLocation , and useHistory . それで、あなたがAを得るルートセットアップがあるならばid パスからparamを指定すると、次のようになります.
/* The Route: */
<Route path="/tab1/:id" exact={true}>
  <Tab1 />
</Route>

/* And inside the Tab1.tsx function: */
const params = useParams<{id: string}>();
// do something with params.id

ラッピング


ちょうどいくつかの迅速な最適化では、我々は、ページのナビゲーションの多くの回からの貸し手を削減することができただけで1回のときにイオニアページを最初にロードします.あまりにも卑しい!
何かコメントを得たり、イオンの周りの何かをカバーしてください.下記のコメントで私を殴ってください、さえずりの上で私を捕えてください.
ハッピーコーディング!