web-dev-qa-db-ja.com

Reactフック:何/なぜ `useEffect`?

新しく提案された React Effect Hook ;について

  1. Effectフック(useEffect())の利点と使用例は何ですか?

  2. なぜそれが望ましいのでしょうか、それがcomponentDidMount/componentDidUpdate/componentWillUnmount(パフォーマンス/読みやすさ)とどう違うのですか?

ドキュメントには、次のように記載されています。

ミューテーション、サブスクリプション、タイマー、ロギング、およびその他の副作用は、関数コンポーネントのメインボディ内では許可されていません(Reactのレンダリングフェーズと呼ばれます)。

しかし、renderメソッドの代わりに、componentDidUpdateなどのライフサイクルメソッドでこれらの動作を行うことは、すでに一般的な知識であったと思います。

また、次のような言及もあります。

レンダリングが画面にコミットされた後、useEffectに渡された関数が実行されます。

とにかくcomponentDidMountcomponentDidUpdateは何をしているのではないですか?

14
Mirodinho
  1. Effectフック(useEffect())の利点と使用例は何ですか?

    メリット

    主に、フックは一般に、より高次のコンポーネントやレンダリングプロップの負担なしに、複数のコンポーネントに共通するステートフルロジックの抽出と再利用を可能にします。

    (特にエフェクトフックの)副次的な利点は、状態依存の副作用がcomponentDidUpdate内で適切に処理されない場合に発生する可能性があるバグを回避できることです(エフェクトフックは、そのような副作用が確実にセットアップされ、引き裂かれるためすべてのレンダリングでダウン)。

    以下に詳述するパフォーマンスと可読性の利点も参照してください。

    ユースケース

    ライフサイクルメソッドを使用してステートフルロジックを実装する任意のコンポーネント— Effectフックは「より良い方法」です。

  2. なぜそれが望ましいのでしょうか、そしてcomponentDidMount/componentDidUpdate/componentWillUnmount(パフォーマンス/読みやすさ)とどう違うのですか?

    なぜそれが望ましいのか

    上記および下記に詳述する利点があるため。

    ライフサイクルメソッドとの違い

    パフォーマンス

    エフェクトフック—

    • ブラウザが画面を更新するのを妨げないため、ライフサイクルメソッドよりも応答性が高くなります。
    • ただし、すべてのレンダリングで副作用を設定して破棄するため、コストがかかる可能性があります…
    • ...特定の状態が更新されていない限り、完全にスキップするように最適化できます。

    読みやすさ

    エフェクトフックの結果:

    • 以前は同じライフサイクルメソッドのセット全体で表現する必要があった無関係の動作を、そのような動作ごとに1つのフックに分割できるため、よりシンプルで保守しやすいコンポーネント。たとえば、次のようになります。

      componentDidMount() {
        prepareBehaviourOne();
        prepareBehaviourTwo();
      }
      
      componentDidUnmount() {
        releaseBehaviourOne();
        releaseBehaviourTwo();
      }
      

      になる:

      useEffect(() => {
        prepareBehaviourOne();
        return releaseBehaviourOne;
      });
      
      useEffect(() => {
        prepareBehaviourTwo();
        return releaseBehaviourTwo;
      });
      

      BehaviourOneに関連するコードがBehaviourTwoに関連するコードから明確に分離されていることに注意してください。以前は、各ライフサイクルメソッド内に混在していました。

    • 複数のライフサイクルメソッド(componentDidMountcomponentDidUpdateの間で共通など)全体で同じコードを繰り返す必要がなくなるため、ボイラープレートが少なくなります。次に例を示します。

      componentDidMount() {
        doStuff();
      }
      
      componentDidUpdate() {
        doStuff();
      }
      

      になる:

      useEffect(doStuff); // you'll probably use an arrow function in reality
      
8
eggyal

これはReactConf2018Dan Abramovのトークの違いを説明する例です。


以下は、以下の例からのいくつかの調査結果です。

  1. フックを使用してボイラープレートコードを少なくする
  2. useEffect()を使用したライフサイクル更新および状態更新へのアクセス
  3. パフォーマンスに関する1つの側面は次のとおりです。

ComponentDidMountやcomponentDidUpdateとは異なり、useEffectに渡された関数は、レイアウトとペイントの後で、遅延イベントの間に起動します

  1. コードの共有は非常に簡単で、useEffect()は同じコンポーネント内で異なる目的のために複数回実装できます。
  2. 配列をuseEffect()フックに2番目の引数として渡すことで、コンポーネントの再レンダリングをより効率的に制御できます。これは、空の配列[]を渡すだけでコンポーネントのマウントとアンマウントでのみレンダリングする場合に非常に効果的です。
  3. 複数のuseEffect()フックを使用して懸念を分離し、以下のように反応します。

フックを使用すると、ライフサイクルメソッド名ではなく、実行内容に基づいてコードを分割できます。 Reactは、コンポーネントが使用するすべてのエフェクトを、指​​定された順序で適用します


クラスの使用:

class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  componentDidMount() {
    document.title = `You clicked ${this.state.count} times`;
  }

  componentDidUpdate() {
    document.title = `You clicked ${this.state.count} times`;
  }

  render() {
    return (
      <div>
        <p>You clicked {this.state.count} times</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Click me
        </button>
      </div>
    );
  }
}

フックの使用:

import { useState, useEffect } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  // Similar to componentDidMount and componentDidUpdate:
  useEffect(() => {
    // Update the document title using the browser API
    document.title = `You clicked ${count} times`;
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}
7
Sakhi Mansoor