React のクラスからフックへの移行

React のクラスからフックへの移行

Reactフック

序文

これまでの 3 年間、私はクラスを使用してフロントエンドの機能ページを書いてきました。実際、フックについてはしばらく前から触れてきました。私が初めてこれに出会ったのは、electron+react プロジェクトに関するコースを視聴していたときでした。当時はelectronを主に見ていたため、hooksについては特に注目していませんでした。また、私が長年クラスに慣れ親しんできたせいもあるかもしれませんが、当時はフックの関数型の記述スタイルに多少抵抗がありました。しかし、業界でフックが好意的に評価されていたため、フックを使用してプロジェクトを開始したいと思ったこともありました。しかし、当時のプロジェクト サイクルと既存のテクノロジー スタックのせいで、それを実践する機会がありませんでした。

最近、新しいプロジェクトに react hooks+ts を使用しているためです。したがって、フックの使用を開始する必要があります。実際、機能開発に関する限り、他のものをコピーするだけでは何も問題はありません。しかし、フックについて体系的かつ深く理解されていないため、多くの場合、なぜこのようにフックを使用するのかが明確ではありません。そこで最近、「React Hooks Core Principles and Practice」を見つけて勉強しました。

フックの使用と、使用法と理由のレベルでフックを使用する理由を再検討します。機能的なライティングの利点についてさらに検討します。実のところ、ある程度、私は表面をなぞっただけです。ここでは、この期間に私が学んだことを記録しているだけです。

なぜフックなのか?

Hooks の大きな特徴は、ビジネス ロジックを再利用できることです。これはフックにおいて特に顕著です。例えば、通常のクラスでウィンドウサイズの変化を監視したい場合、実装後にコンポーネント内に監視イベントを追加する必要があります。しかし、このウィンドウサイズ監視機能が別の場所でも必要になった場合、このロジックコードは再利用できず、そのコンポーネント内でしか書き換えることができません。ただし、フックでは、監視ロジック コードのこの部分をフック モードでカプセル化し、論理的な再利用を完全に実現できます。

クラス用

  • React のキャリアとして Class を使用する場合:
  • コンポーネントは相互に継承せず、クラス継承機能も利用しません。UI は状態駆動型であり、すべてのメソッドは内部的に呼び出されるか、ライフサイクル メソッドとして自動的に呼び出されます。クラスのインスタンスメソッドを呼び出す機能は使用されていない

機能について

React の中核の 1 つは、State データから View レベルへのバインディングを実現することです。関数を使用するのは、実際には、状態からビューへのマッピングの問題を解決するより良い方法です。ただし、React のキャリアとして関数を使用すると、関数内の状態の保存ライフサイクル メソッドという 2 つの問題が発生します。

  • フックは、外部データを関数の実行にバインドすることで、上記の 2 つの問題をどのように解決しますか。データが変更されたときに関数が自動的に再実行されるようにします。このように、UI の表示に影響を与える外部データは、このメカニズムを通じて React の関数コンポーネントにバインドできます。
  • フックの理解: 変更される可能性のあるデータ ソースまたはイベント ソースにターゲット結果をフックします。フックされたデータまたはイベントが変更されると、ターゲット結果を生成するコードが再実行され、更新された結果が生成されます。

図: 関数コンポーネント自体などの実行プロセス (実行) は、従来の状態、URL、またはウィンドウのサイズにバインド (フック) できます。このように、状態、URL、またはウィンドウ サイズが変更されると、関数が再実行され、更新された結果が生成されます。

クラスとフック

  • クラス コンポーネントと比較すると、関数コンポーネントは State => View の論理関係に沿っているため、React コンポーネントの実行を表現するのに適しています。しかし、ステータス、ライフサイクル、その他のメカニズムが欠如しているため、その機能は常に限られていました。 Hooksは、Reactキャリアとして関数コンポーネントの状態ライフサイクルの制限された問題を解決し、その機能を最大限に活用できるようにします。
  • フックにフックされたオブジェクトは、独立したデータソースまたは別のフックの実行結果である可能性があり、これにより、フックの最大の利点であるロジックの再利用が実現します。
  • ロジックの再利用を簡素化
    • クラスメソッドの場合: ロジックの再利用のために高次コンポーネントの設計パターンを使用します。たとえば、ウィンドウのサイズ変更機能を再利用したい場合は、UI のない外部コンポーネントを定義し、関連するサイズ変更ロジックの定義を記述してから、データ結果を属性の形式で子コンポーネントに渡す必要があります。コンポーネントがこのロジックを再利用したい場合は、このコンポーネントでラップして返す必要があります。全体として、外部状態を渡すには、UI のない外部コンポーネントを定義する必要があり、このコンポーネントは再利用可能なロジックをカプセル化するためだけのものです。 **頻繁に使用すると、高レベルコンポーネントごとにノードのレイヤーが追加され、デバッグなどに大きな負担がかかります。
//クラス内の高レベルコンポーネントは resize メソッドの再利用を実装します //1. 高レベルコンポーネントの宣言 const withWindowSize = Component => {
  // ウィンドウサイズを監視するロジックのみを含む高レベルコンポーネント WrappedComponent を生成します。class WrappedComponent extends React.PureComponent {
    コンストラクタ(props) {
      スーパー(小道具);
      この状態 = {
        サイズ: this.getSize()
      };
    }
    コンポーネントマウント() {
      window.addEventListener("サイズ変更", this.handleResize); 
    }
    コンポーネントのマウントを解除します(){
      window.removeEventListener("サイズ変更", this.handleResize);
    }
    取得サイズ() {
      window.innerWidth > 1000 ? "large" : "small" を返します。
    }
    ハンドルサイズ変更 = () => {
      現在のサイズを取得します。
      this.setState({
        サイズ: this.getSize()
      });
    }
    与える() {
      // ウィンドウ サイズを実際のビジネス ロジック コンポーネントに渡します。 return <Component size={this.state.size} />;
    }
  }
  WrappedComponent を返します。
};
//2. コンポーネント MyComponent は高階コンポーネントの resize 関数を使用します。クラス MyComponent は React.Component を拡張します{
  与える() {
    const { size } = this.props;
    if (size === "small") return <SmallComponent />;
    それ以外の場合は <LargeComponent /> を返します。
  }
}
// withWindowSize を使用して高次コンポーネントを生成し、サイズ属性を生成して実際のビジネス コンポーネントに渡します。export default withWindowSize(MyComponent); 
  • Hooks メソッドの場合: resize が実装されている場合、ウィンドウ サイズは単なる外部データ状態になります。フックを使用してこれをカプセル化し、バインド可能なデータ ソースに変換するだけです。ウィンドウのサイズが変更されると、コンポーネントもコードを再レンダリングします。これにより、より簡潔で直感的になり、追加のコンポーネント ノードは生成されません。
//Hooksはhooksメソッドを使用してサイズ変更ロジックを再利用します //useWindowSizeフックを定義します
定数getSize = () => {
  window.innerWidth > 1000 ? "large" : "small" を返します。
}
定数useWindowSize = () => {
  const [size, setSize] = useState(getSize());
  使用効果(() => {
  定数ハンドラ = () => {
      サイズを設定する(サイズを取得する())
    };
    window.addEventListener('resize', ハンドラ);
    戻り値 () => {
      window.removeEventListener('resize', ハンドラー);
    };
  }, []);
  サイズを返します。
};
//関数コンポーネントでこのフックを使用する
constデモ = () => {
  定数サイズ = useWindowSize();
  if (size === "small") return <SmallComponent />;
  それ以外の場合は <LargeComponent /> を返します。
};
  • 関心の分離に役立ちます

フックは、同じビジネス ロジックのコードを可能な限り集約できます。クラス コンポーネントでは、同じビジネス ロジック コードをクラス コンポーネントの異なるライフ サイクル メソッドに分散させる必要があります。

画像

図: 左側はクラス コンポーネント、右側はフックと組み合わせた関数コンポーネントです。青と黄色は異なるビジネス機能を表す

フックはコンポーネントの状態を保存し、ライフサイクルをどのように使用しますか?

React は、 useStateuseEffectuseCallbackuseMemouseRefuseContextなど、合計 10 個のHooksを提供します。

1. useState: 関数が状態を維持できるようにする

私たちが従うべき原則の 1 つは、次のような計算可能な値を状態に保存してはならないということです。

  • props から渡された値。場合によっては、props によって渡された値を直接使用できず、並べ替えなどの特定の計算を行った後に UI に表示する必要があります。したがって、必要なのは、結果を使用するたびに結果を再ソートするか、結果を直接状態に置くのではなく、何らかのキャッシュ メカニズムを使用することです。
  • URL から読み取られた値。たとえば、URL 内のパラメータを読み取って、それをコンポーネント状態の一部として使用する必要がある場合もあります。そうすれば、それを読み取って直接状態に置くのではなく、必要なときに毎回 URL から読み取ることができます。
  • クッキーとlocalStorageから読み取られた値。一般的に言えば、読み出して状態に置くのではなく、必要なときにその都度直接読み取られます。

2. useEffect: 副作用を実行する

副作用とは、現在の実行の結果に影響を与えないコードの一部です。たとえば、関数の外部で変数を変更する場合は、リクエストを開始する必要があります。形式: useEffect(callback, dependencies) 。これは、 componentDidMountcomponentDidUpdatecomponentWillUnmount 3 つのライフサイクル メソッドをカバーします。つまり、useEffect は依存関係を決定し、コンポーネントがレンダリングされるたびにそれを実行します。

useEffect を使用する際の注意点:

依存関係がない場合、各レンダリング後に再実行されます。

使用効果(()=>{
	console.log('re-render') //レンダリングが完了するたびに実行})
  • 空の配列が依存関係として使用された場合、最初の実行時にのみトリガーされ、対応するクラスコンポーネントはcomponentDidMountになります。
使用効果(()=>{
  console.log('did mount') //componentDidMount と同等
},[])
  • コンポーネントが破棄されたときにクリーンアップを実行する関数を返すことができます。
const [size,setResize] = useState({})
使用効果(()=>{
	定数ハンドラ = () => {
    サイズを設定する()
	}
	window.addEventListener('resize',ハンドラ)
	戻り値 () =>{
		window.removeEventListener('resize',ハンドラ)
	}
},[])

要約する

  • useEffect で使用される 4 つのシナリオは、各レンダリング後に実行されます。2 番目の依存関係パラメータは提供されません。たとえば、useEffect(() => {})。
  • 最初のレンダリング後にのみ実行されます。依存関係として空の配列を提供します。たとえば、useEffect(() => {}, [])。
  • 初めて実行され、依存関係が変更された後: 依存関係の配列を提供します。たとえば、useEffect(() => {}, [deps])。
  • コンポーネントがアンマウントされた後に実行され、コールバック関数を返します。たとえば、useEffect() => { return () => {} }, [])。

この記事はこれで終わりです。皆さんのお役に立てれば幸いです。また、123WORDPRESS.COM のその他のコンテンツにも注目していただければ幸いです。

以下もご興味があるかもしれません:
  • React Hook: ステートフックの使い方
  • React Hook: Effect Hookの使い方
  • React の 10 個のフックの紹介
  • React Hooksの詳細な説明
  • Reactのフックについて学ぼう

<<:  DockerHubを自分で構築する方法

>>:  MySQL データ操作 - DML ステートメントの使用

推薦する

2008 年の Web デザインにおける 10 の経験

<br />インターネットは絶えず変化しており、BusinessWeek.com は専門...

CSS のオーバーフロー:hidden エラーの解決方法

失敗の原因今日、カルーセルを書いていたときに、overflow;hidden; が失敗する可能性があ...

MySQL はカスタムシーケンスを使用して row_number 関数を実装します (詳細な手順)

いくつかの記事を読んだ後、ようやく MySQL で row_number() ソートを実装する方法が...

Vue.js ソースコード解析のカスタム手順の詳細な説明

序文コア機能のデフォルトの組み込みディレクティブ (v-model および v-show) に加えて...

CentOS7 で yum を使用して PostgreSQL と PostGIS をインストールする方法

1. yumソースを更新するCentOS7 のデフォルトの yum リポジトリの PostgreSQ...

JS、CSS スタイルのリファレンスの記述

CS: ... 1. <link type="text/css" href...

中国のウェブサイトユーザーエクスペリエンスランキング

<br />ユーザーエクスペリエンスは中国のウェブサイトでますます重視されており、ユーザ...

vsCodeはワンクリックでvueテンプレートを生成します

1. ショートカットCtrl + Shift + Pを使用してコンソールを呼び出します 2、「スニペ...

CSS 属性を使用してマウス イベントをブロックする方法 (マウス クリックは上位の要素を貫通する可能性があります)

由来: 数日前、テスターから写真を見るという要件が送られてきました。 この要件を見たとき、私は少し混...

MySQL で null を置き換える IFNULL() および COALESCE() 関数の詳細な説明

MySQLではisnull()関数をnull値の代わりとして使用することはできません。次のように:ま...

JavaScript 事前分析、オブジェクトの詳細

目次1. 事前分析1. 変数の事前解析と関数の事前解析1. 変数の事前解析2. 機能事前分析2. 事...

ウェブページの再設計の7つの主要要素 ウェブページの再設計の7つの主要要素を共有する

Shopify Plus は、私たちが設立した e コマース プラットフォームのエンタープライズ バ...

Dockerfileを使用してApacheイメージを作成する方法

目次1. Dockerイメージ2. 既存のイメージに基づいてインスタンスを作成する3. ローカルテン...

文字列から指定された文字を削除または抽出する JavaScript メソッド (非常によく使用されます)

目次1. 部分文字列() 2. サブストラクチャ() 3.インデックス() 4.最後のインデックス(...

Dockerの動作モードと原理の詳細な説明

次の図に示すように: 仮想マシンと Docker を使用するとき、「なぜ Docker は VM よ...