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 ステートメントの使用

推薦する

Docker は次の「Linux」になれるか?

Linux オペレーティング システムは過去 20 年間にわたってデータ センターに革命をもたらし...

Linuxのpasswdコマンドの使用

1. コマンドの紹介passwd コマンドは、ユーザー パスワード、アカウント ロック、パスワードの...

Dockerボリュームのファイルマッピング方法

背景ブロックチェーン ログ モジュールで作業しているときに、コンテナーが実行されている場合は、ログ ...

MySQLデータベースを使い始めるための最初のステップはテーブルを作成することです

データベースを作成する右クリック - 新しいデータベースを作成ライブラリ名を入力し、文字セットと並べ...

HTMLは無効なテーブル幅設定の問題を解決します

テーブルに table-layer:fixed スタイルを設定し、テーブル内の行が結合されていること...

MySQLデータベースで列を追加、削除、変更する方法

この記事では、例を使用して、MySQL データベースの列を追加、削除、および変更する方法について説明...

Web Storage APIの使用に関する簡単な説明

目次1. ブラウザのローカルストレージ技術1.1、セッションストレージ1.2、ローカルストレージ2....

MySQL 面接でよく聞かれる質問への回答

序文:さまざまな技術職の面接では、MySQL 関連の質問がよくされるようです。開発職の面接でも運用職...

el-tree での不完全なテキスト表示の解決策

目次方法1: 水平スクロールバーを設定する最も簡単な方法方法2(新規):ドラッグバーを追加して外側の...

MySQL ピボットテーブルについての簡単な説明

次のような製品部品表があります。一部 部品ID 部品タイプ 製品ID ---------------...

LinuxシステムでFuserコマンドを使用する方法

Fuser コマンドとは何ですか? fuser コマンドは、特定のファイル、ディレクトリ、またはソケ...

ReactにおけるuseRefの具体的な使い方

React の経験がある人なら、コンポーネントインスタンスオブジェクトや DOM オブジェクトを取得...

HTMLページの読み込み速度を上げる方法

(1)HTTPリクエストを減らす。 (リソース ファイルをマージし、イメージ スプライトを使用します...

CentOS 6.5 インストール mysql5.7 チュートリアル

1. 新機能MySQL 5.7 はエキサイティングなマイルストーンです。デフォルトの InnoDB ...