Learning React(12.React不要なレンダリングを除去)

17967 ワード

1.不要なレンダリングを避ける


01.renderメソッドの正体

  • renderの役割は、JSXを生成して各構成部品を表示し、親構成部品に戻るのを助けることです.
  • 自動呼び出し
  • render
  • 要素の属性が更新された場合、
  • 要素の状態属性が更新された場合、
  • .
  • 親コンポーネントのレンダリング方法を呼び出すと
  • になります.
  • renderメソッドを呼び出す必要がない場合に
  • を呼び出す.
  • コンポーネントは、1つまたは2つの小さな規模しかない場合、パフォーマンスの面で大きな違いがある可能性がありますが、コンポーネントが複雑になるにつれて、パフォーマンスの面で大きな問題が発生する可能性があります.
  • 02.render呼び出しの最適化

  • 前回のSlide Menuから、
  • この場合、MenuButtonレンダリングのボタンをクリックすると、MenuContainerのvisibleと呼ばれる状態属性の値が更新され、その属性がクラス値が更新される
  • 03.render呼び出しについて

  • の各コンポーネントのレンダリング方法では、コンソールを使用して呼び出し順序を確認します.
  • -1. MenuContainer.js

    import React, { Component } from "react";
    import MenuButton from "./MenuButton";
    import Menu from "./Menu";
    
    class MenuContainer extends Component {
      constructor(props) {
        super(props);
    
        this.state = {
          visible: false,
        };
    
        this.handleMouseDown = this.handleMouseDown.bind(this);
        this.toggleMenu = this.toggleMenu.bind(this);
      }
    
      handleMouseDown(e) {
        this.toggleMenu();
    
        console.log("clicked");
        e.stopPropagation();
      }
    
      toggleMenu() {
        this.setState({
          visible: !this.state.visible,
        });
      }
    
      render() {
        console.log("Rendering : MenuContainer");
        return (
          <div>
            <MenuButton handleMouseDown={this.handleMouseDown} />
            <Menu
              handleMouseDown={this.handleMouseDown}
              menuVisibility={this.state.visible}
            />
            <div>
              <p>Can you spot the item that doesn't belong?</p>
              <ul>
                <li>Lorem</li>
                <li>Ipsum</li>
                <li>Dolor</li>
                <li>Sit</li>
                <li>Bumblebees</li>
                <li>Aenean</li>
                <li>Consectetur</li>
              </ul>
            </div>
          </div>
        );
      }
    }
    
    export default MenuContainer;

    -2. MenuButton.js

    import React, { Component } from "react";
    import "./MenuButton.css";
    
    class MenuButton extends Component {
      render() {
        console.log("Rendering : MenuButton");
        return (
          <button
            id="roundButton"
            onMouseDown={this.props.handleMouseDown}
          ></button>
        );
      }
    }
    
    export default MenuButton;

    -3. Menu.js

    import React, { Component } from "react";
    import "./Menu.css";
    
    class Menu extends Component {
      render() {
        console.log("Rendering : Menu");
        var visibility = "hide";
    
        if (this.props.menuVisibility) {
          visibility = "show";
        }
        return (
          <div
            id="flyoutMenu"
            onMouseDown={this.props.handleMouseDown}
            className={visibility}
          >
            <h2>
              <a href="/">Home</a>
            </h2>
            <h2>
              <a href="/">About</a>
            </h2>
            <h2>
              <a href="/">Contact</a>
            </h2>
            <h2>
              <a href="/">Search</a>
            </h2>
          </div>
        );
      }
    }
    
    export default Menu;

    -4.render呼び出しcheck

  • プロパティが変更されるたびに、すべてのコンポーネントのrenderが呼び出されます.
  • しかし実際の状態変化のMenuContainerとMenuとは異なり、MenuButtonは属性変化のない関数
  • を伝達する.
  • このように見ると、レンダリングはMenuButtonに呼び出される必要はありません!


  • 04.renderメソッドの呼び出しを避ける


    -1.shouldComponentUpdateの再定義

  • 法は反応ライフサイクル法の1つであり、
  • である.
  • このメソッドはrenderメソッド呼び出しの前に呼び出され、falseを返すとrenderメソッド「胡秋玲」を防止することができる.
  • shouldComponentUpdateを再定義して、属性またはステータスが変更されたかどうかを判断するソリューション
  • _1. shouldComponentUpdate false return

  • は、画面に表示されたレンダリング後の状態が最初に変化したときに呼び出されなかったことを確認することができる!
  • ただし、falseを無条件に返すと、レンダリングが必要になることを防ぐことができるので、shouldComponentUpdateメソッドの引数を使用してレンダリングを防ぐことができます!
  • import React, { Component } from "react";
    import "./MenuButton.css";
    
    class MenuButton extends Component {
      shouldComponentUpdate(nextProps, nextState) {
        return false;
      }
    
      render() {
        console.log("Rendering : MenuButton");
        return (
          <button
            id="roundButton"
            onMouseDown={this.props.handleMouseDown}
          ></button>
        );
      }
    }
    
    export default MenuButton;



    _2. shouldComponentUpdate used parameters

  • nextPropsパラメータを使用して、現在ダウンロードされているpropsとメソッド呼び出し時のpropsを比較し、変化があればreturn trueが変化しなければreturn falseを実行します!
  • これにより、handleMousedownが更新されると、return trueを使用して
  • を調整することができます.
    import React, { Component } from "react";
    import "./MenuButton.css";
    
    class MenuButton extends Component {
      shouldComponentUpdate(nextProps, nextState) {
        if (this.props.handleMouseDown === nextProps.handleMouseDown) {
          return false;
        } else {
          return true;
        }
      }
    
      render() {
        console.log("Rendering : MenuButton");
        return (
          <button
            id="roundButton"
            onMouseDown={this.props.handleMouseDown}
          ></button>
        );
      }
    }
    
    export default MenuButton;



    -3.PureCompentの使用

  • に関連する属性または状態の変化がない場合でも、構成部品を再レンダリングすることがよくあります.
  • shouldComponentUpdateを再定義し、属性や状態が変更されているかどうかを確認する解法がありますが、今回は自動的に処理する素子を使用します!
  • コンポーネントを単純にPureCompentに変更するだけで簡単
  • ではすべてのコンポーネントをPureCompentとして使えばいいのではないでしょうか.
  • デフォルトではPureCompentは推奨されません
  • PureCompentが浅い比較を実行したため
  • とは、属性または状態の変更を不完全に確認することである.
  • 多くの場合大きな問題はありませんが、場合によってはそうではない場合があります.
  • PureCompentを使用する場合、必ず考慮すべきことは
  • です.
  • はまた、shouldComponentUpdateを再定義して、必要な他の更新ロジックを直接記述する必要がある場合があります.
  • PureCompentとShouldComponentUpdateを同時に使用することはできません
  • PureCompentを使用する場合の最大の問題はパフォーマンスです!
  • 要素の属性または状態が変更されたかどうかを確認するには、比較が浅い場合でも時間
  • を計算する必要があります.
    親構成部品をレンダーするたびに、
  • Workerが子構成部品をレンダーするかどうかを変更することを覚えておいてください.
  • 、特に福沢巴のUIでは、このようなことがより頻繁に発生します.
  • 上記の問題だけに注目すれば、基本的にPureCompentを使っても大丈夫です
    import React, { PureComponent } from "react";
    import "./MenuButton.css";
    
    class MenuButton extends PureComponent {
      // shouldComponentUpdate(nextProps, nextState) {
      //   if (this.props.handleMouseDown === nextProps.handleMouseDown) {
      //     return false;
      //   } else {
      //     return true;
      //   }
      // }
    
      render() {
        console.log("Rendering : MenuButton");
        return (
          <button
            id="roundButton"
            onMouseDown={this.props.handleMouseDown}
          ></button>
        );
      }
    }
    
    export default MenuButton;