Reactにおけるフックの一般的な使用法

Reactにおけるフックの一般的な使用法

1. フックとは何ですか?

React フックは、React 16.8 で導入されたメソッドで、関数コンポーネントにクラス コンポーネントのような状態、参照、ライフサイクルなどのプロパティを持たせることができます。

2. フックはなぜ現れるのでしょうか?

関数コンポーネントは、グローバル世界における普通の関数です。非厳格モードでは this は window を指しますが、React 内部では厳格モードがオンになっています。このとき、 this は undefined を指し、クラスコンポーネントのように state や ref を使用することはできません。関数コンポーネントで定義された変数はローカルであり、コンポーネントが更新されると再定義され、保存することはできません。そのため、フックが登場する前は、関数コンポーネントには大きな制限があり、通常はクラスコンポーネントを使用してコードを記述していました。

3. よく使われるフックは何ですか?

(1)使用状態

機能コンポーネントが状態を保存できるようにするフック。このフックの入力パラメータは状態の初期値で、戻り値は配列です。配列の最初のパラメータは状態の値で、2 番目のパラメータは状態を変更するメソッドです。

// 初期化 const [ count, setCount ] = useState(0)
// 更新 setCount(count+1)

(2)使用効果

機能コンポーネントは、ライフサイクルのフックをシミュレートするために使用されます。コンポーネントのマウント、更新、アンインストールの 3 つの段階、つまり、componentDidMount、componentDidUpdate、componentWillUnmount をシミュレートできます。

useEffect のパラメータの 1 つは関数で、コンポーネントがマウントおよび更新されるときに実行されるコンテンツを表します。関数内で返される別の関数は、コンポーネントがアンインストールされるときに呼び出される関数を表します。

2 番目のパラメータはオプションで、配列に渡すことができます。配列は空にすることができます。これは、状態の変化に依存しないことを意味します。つまり、コンポーネントがマウントされるときにのみ実行されます。このフックは、その後の状態の変化があっても呼び出されません。配列内に 1 つ以上の状態を定義することもできます。つまり、状態が変化するたびにこのフックが実行されます。

使用効果(()=>{
  // これはcomponentDidMountをシミュレートします
}, [])

使用効果(()=>{
  // これはcomponentDidMountをシミュレートし、カウントが変更されたときにcomponentDidUpdateを実行します
}, [カウント])

使用効果(()=>{
  戻り値 () =>{
  // これはcomponentWillUnmountをシミュレートします
  }
}, [])

(3)コンテキストを使用する

フック前は、通常、xxxContext.Provider と xxxContext.Consumer を介してコンテキスト値を渡したり取得したりしていました。フック後は、コンテキストを渡す方法は変更されませんが、子要素がコンテキストを取得する方法はより簡単になります。

// 以前の定義 const CountContext = React.createContext()
 <CountContext.Provider 値 = {{ count: 10 }}>
     <...カスタマイズされたコンポーネント>
 </CountContext.Provider>

// 子要素 <CountContext.Consumer>
    { 値 => { console.log(値.count) }} //10
</CountContext.Consumer>

//コンテキストを使用してメソッドを取得します const countObj = useContext(CountContext)
コンソール.log(countObj.count) // 10

(4)useRef

useRef の使用方法は、クラス コンポーネントの createRef と似ています。関数のライフサイクル全体を通じて変更されない ref オブジェクトを返します。この機能に基づいて、一般的な使用法が 2 つあります。

① DOM要素またはコンポーネントで使用すると、現在の属性を通じてDOM要素またはクラスコンポーネントのインスタンスオブジェクトを取得できます。注意すべき点は、useRef でも createRef でも、コールバック形式や文字列形式の ref でも、関数コンポーネントの this は undefined を指しており、インスタンス オブジェクトがないため、関数コンポーネントに直接定義することはできないということです。forwardRef を介して関数コンポーネント内の DOM 要素にのみ定義できます。

// これにより、関数コンポーネントに渡された ref が関数コンポーネント内の入力タグにバインドされます。import React, { useRef, forwardRef } from 'react'

// 関数式を使用して関数コンポーネントを定義します const InputCom = forwardRef((props, ref) => {
    <input ref={ref}/> を返します
 })

デフォルト関数refDemo()をエクスポートする{
    定数comRef = useRef()
    戻り値(<div>
       <InputCom ref={comRef}/>
         </div>)
  }

②手動で変更されない限り、ライフサイクルを通じて変更されないデータを保存する

const [ count, setCount ] = useState(0)
定数 prevCount = useState(count)
// カウントが変更されると、コンポーネントは countuseEffect(()=>{ の以前のデータを更新して保存します。
  prevCount.current = カウント
}, [カウント])

(5)リデューサーを使う

useReducer は、useState のアップグレード版に相当します。その機能は useState に似ており、どちらも状態を保存するために使用されますが、違いは、複雑なデータを処理するために、reducer の純粋な関数を定義できることです。

// データを処理する純粋なリデューサー関数を定義します function Reducer(prevState, action){
  スイッチ(アクション.type){
    ケース '増分':
      {...prevState、count: prevState.count + 1 } を返します。
    ケース '減少':
      {...prevState、count: prevState.count - 1 } を返します。
    デフォルト:
      前の状態を返す
  }
}

// 状態を初期化する const [ count, dispatch ] = useReducer(reducer, { count: 0 })
// 状態を変更します。この時点での変更には、受信リデューサー関数が処理できるようにアクションをディスパッチする必要があります。dispatch({ type: 'increment' })

(6)コールバックを使用する

関数コンポーネントでは、状態が更新されるたびに、カスタム関数を再宣言して再定義する必要があります。関数が子コンポーネントに props として渡されると、子コンポーネントの不要な再レンダリングが発生します。子コンポーネントは、親コンポーネントの変更された状態を使用しない場合があります。このとき、useCallback を使用してパフォーマンスを最適化できます。関数に記憶された値を返します。依存する状態が変更されていない場合、関数は再作成されず、子コンポーネントの不要な再レンダリングは発生しません。

React をインポートします。{useState、useCallback、memo} を 'react' からインポートします。
const AddBtn = memo((props)=>{ // 関数式を使用して関数コンポーネントを定義します return<button onClick={props.increment}>+1</button>
})

デフォルト関数CallBackPerformance()をエクスポートする{
    const [ count, setCount ] = useState(0)
    const [ show, setShow ] = useState(true)
    定数増分1 = () => {
        console.log('increment1が呼び出されました')
        setCount(カウント+1)
    }

   const increment2 = useCallback(()=>{ // useCallback を使用して最適化された関数 console.log('increment2 が呼び出されました')
         setCount(カウント+1)
    }、[カウント])

    戻り値(<div>
            <div>現在のカウント: {count}</div>
            <AddBtn 増分={increment1} 名前="1"/>
            <AddBtn 増分={increment2} 名前="2"/>
            <button onClick={e => setShow(!show)}>表示を切り替える</button>
        </div>)
}
// 表示状態が変化すると、サブコンポーネントの increment1 は再レンダリングされますが、 increment2 は再レンダリングされません。

(7)メモを使う

useMemo も記憶された値を返します。依存するコンテンツが変更されない場合、この値は変更されません。useMemo と useCallback の違いは、useMemo は渡された関数で値を返す必要があることです。この値はオブジェクトまたは関数にすることができます。形式は次のとおりです。

メモを使う(()=>{
  {count} を返す
}, [カウント])

// useCallbackを使用する場合
   定数インクリメント2 = useCallback(()=>{
    setCount(カウント+1)
}、[カウント])

//useMemo を使用して useCallback をシミュレートする
定数インクリメント2 = useCallback(()=>{
    戻り値 () =>{
        setCount(カウント+1)
    }
}、[カウント])

// useMemo の適用シナリオは、複雑な計算を実行する必要がある場合です。
// 計算された値は変更されていないため、更新ごとに再計算する必要はありません import React, { useState, useMemo } from 'react'
const calculateNum = (count) => {
    console.log('合計が再計算されました')
    合計を0にする
    for(let i = 0; i <= count; i++){
        合計 += i
    }
    合計を返す
}

デフォルト関数ComplexUseMemo()をエクスポートする{
    const [ count, setCount ] = useState(10)
    const [ show, setShow ] = useState(true)
    定数合計 = useMemo(()=>{
        calculateNum(count) を返す
    }, [カウント])
    戻り値(<div>
        <div>{合計}</div>
        <button onClick={e=>setCount(count+1)}>+1</button>
        <button onClick={e=>setShow(!show)}>表示を切り替える</button>
    </div>)
}

(8)命令型ハンドルを使用する

これは forwardRef と組み合わせて使用​​します。 forwardRef を使用して機能コンポーネントの DOM 要素を指定すると、親コンポーネントは指定された DOM 要素を任意に操作できます。 useImperativeHandle は、このような動作を制御し、親要素が操作できる子要素のメソッドを指定するために使用します。

'react' から React をインポートします。{useRef、useImperativeHandle、forwardRef}
const InputComp = forwardRef((props, ref)=>{
  定数childInputRef = useRef()
  命令型ハンドルを使用します(ref, ()=>({
    フォーカス: ()=>{
      childInputRef.current.focus()
    }
  })、[childInputRef.current]) より

  <input ref={childInputRef}></input> を返します。
})

デフォルト関数ImperativeHookDemo()をエクスポートします。
  定数 inputRef = useRef()
  戻り値(<div>
      <InputComp ref={inputRef}/>
      <button onClick={e=>inputRef.current.focus()}>フォーカス</button>
    </div>)
}

(9)レイアウト効果を使用する

このメソッドは us​​eEffect に似ていますが、実行順序が少し異なります。useEffect はコンポーネントがレンダリングされて画面に描画された後に行われ、useLayoutEffect はレンダリングと画面への描画の間に行われます。

4. フックをカスタマイズするには?

フックは機能コンポーネントでのみ定義でき、通常の関数では使用できません。上記のフックを使用して、複数のコンポーネントが呼び出すいくつかのメソッドをカプセル化する場合は、フックをカスタマイズする必要があります。カスタムフックの名前は、関数名の前に「use」を追加し、関数名を saveInfo から useSaveInfo に変更します。

上記は、React でよく使われるフックの詳しい使い方です。React フックの使い方の詳細については、123WORDPRESS.COM の関連記事もご覧ください。

以下もご興味があるかもしれません:
  • React Hooksコンポーネント間で値を渡す方法の詳細な説明(tsを使用)
  • ReactHooks バッチ更新状態とルートパラメータの取得例の分析
  • React Hooksの詳細な説明
  • React Hooksを使用する際のよくある落とし穴
  • 30分でReact Hooksを包括的に理解できます
  • Reactフックの仕組み
  • React の 10 個のフックの紹介

<<:  Linux CentOS でスケジュールされたバックアップ タスクを設定する方法

>>:  MYSQL ログとバックアップおよび復元の問題の詳細な説明

推薦する

Hadoop におけるネームノードとセカンダリネームノードの動作メカニズムの説明

1) プロセス 2) FSImageと編集NodeNode は HDFS の頭脳です。ファイルシステ...

vue+django でファイルをダウンロードする例

目次1. 概要2. Django プロジェクト3. Vueプロジェクト1. 概要プロジェクトで、ダウ...

ReactのPropsの簡単な比較

目次クラスコンポーネントのプロパティ比較浅い同等の浅い比較機能コンポーネントの簡単な比較先週面接に行...

IDEA2021 tomcat10 サーブレットの新しいバージョンの落とし穴

私が学習していたときに使用していたバージョンは比較的新しいものであり、インターネット上のチュートリア...

Docker での Redis の永続ストレージの詳細な説明

この章では、dockerの下にあるSpring BootプロジェクトでRedisを操作し始めます。準...

PXEを使用してLinuxシステムを自動的に展開する方法

目次背景DHCPの設定DHCP ファイル (動的ホスト構成プロトコル) の編集tftp 設定sysl...

MySQL エラー: ロックを取得しようとしたときにデッドロックが見つかりました。トランザクションの解決策を再起動してください

問題を見つける最近、以前のデータを入力していたときに、プログラムが突然次のエラーを報告しました。 [...

カルーセル効果を実現するための純粋なjs

この記事では、カルーセルマップの効果を実現するためのjsの具体的なコードを参考までに共有します。具体...

MySQL並列レプリケーションの簡単な説明

1. 並列レプリケーションの背景まず、並列レプリケーションの概念はなぜ存在するのでしょうか? 1. ...

Linuxネットワーク設定の基本操作コマンドを詳しく解説

目次ネットワーク構成を表示するネットワークインターフェース情報を表示する---ifconfigルーテ...

バックエンドの権限に基づいてナビゲーション メニューを動的に生成する Vue-router のサンプル コード

目次js の1. グローバルガードを登録する2. Vuex 状態管理グローバルキャッシュルート3. ...

デザインストーリー: ナンバープレートを覚えられない警備員

<br />私が住んでいる地域では、コミュニティに出入りする車両を管理するために、コミュ...

Windows で Mysql を起動したときに 1067 が表示される場合の解決策

数日前に仕事を始めて、Mysql をインストールしたところ、開くことができました。今日、会社に行った...

MySQLインデックスの簡単な分析

データベース インデックスは、テーブル操作の速度を向上させることを目的としたデータ構造です。高速なラ...

CentOS 7 に mysql5.7 の解凍バージョンをインストールするチュートリアル

1. mysqlの圧縮パッケージを/usr/localフォルダに解凍し、名前をmysqlに変更します...