序文 React はバージョン v16.8 で新しい機能 React Hooks をリリースしました。私の意見では、React Hooks を使用すると、以前のクラス コンポーネントに比べて次のような利点があります。
この記事では、React Hooks のほとんどの機能を理解し、上手に使用できるように、使用シナリオに基づいた例を紹介します。 ブログのgithubアドレスはhttps://github.com/fengshi123/blogです。 1. ステートフック1. 基本的な使い方関数状態(){ 定数[count, setCount] = useState(0); 戻る ( <div> <p>クリック回数は {count} 回です</p> <ボタンのクリック時={() => setCount(count + 1)}> クリックしてください </ボタン> </div> ) } 2. 更新更新方法には、直接更新と機能更新の 2 種類があります。それぞれのアプリケーション シナリオの違いは次のとおりです。
// setState(newCount) を直接更新します。 // 機能更新 setState(prevCount => prevCount - 1); 3. 合併を実現するクラス コンポーネントの setState メソッドとは異なり、useState は更新されたオブジェクトを自動的にマージせず、直接置き換えます。関数 setState をスプレッド演算子と組み合わせて使用することで、オブジェクトのマージと更新の効果を実現できます。 setState(前の状態 => { // Object.assignも使用できます {...prevState、...updatedValues} を返します。 }); 4. 遅延初期化状態initialState パラメータはコンポーネントの初期レンダリングでのみ有効になり、後続のレンダリングでは無視されます。適用シナリオは次のようになります。初期状態の作成にコストがかかる場合、たとえば複雑な計算によって取得する必要がある場合、関数を渡して計算し、関数内で初期状態を返すことができます。この関数は、最初のレンダリング時にのみ呼び出されます。 const [状態、setState] = useState(() => { 定数初期状態 = someExpensiveComputation(props); 初期状態を返します。 }); 5. 重要なポイント(1) クラス内のthis.setStateとは異なり、Hookは状態変数をマージするのではなく常に置き換えることで状態変数を更新します。 エフェクトフック1. 基本的な使い方関数 Effect(){ 定数[count, setCount] = useState(0); 使用効果(() => { console.log(`${count} 回クリックしました`); }); 戻る ( <div> <p>クリック回数は {count} 回です</p> <ボタンのクリック時={() => setCount(count + 1)}> クリックしてください </ボタン> </div> ) } 2. クリアな操作メモリ リークを防ぐために、コンポーネントがアンインストールされる前にクリーンアップ関数が実行されます。コンポーネントが複数回レンダリングされる場合 (通常はそうなります)、次のエフェクトが実行される前に前のエフェクトがクリアされます。つまり、前のエフェクトの return 関数が最初に実行され、次にこのエフェクトの non-return 関数が実行されます。 使用効果(() => { サブスクリプション = props.source.subscribe(); 戻り値 () => { // サブスクリプションをクリアします subscription.unsubscribe(); }; }); 3. 実行期間componentDidMount や componentDidUpdate とは異なり、useEffect でスケジュールされたエフェクトはブラウザの画面更新をブロックしないため、アプリの応答性が向上します (componentDidMount や componentDidUpdate はブラウザの画面更新をブロックします)。 4. パフォーマンスの最適化デフォルトでは、React はブラウザが画面のレンダリングを完了するのを待つたびにエフェクトの呼び出しを遅らせます。ただし、2 回の再レンダリング間で特定の値が変更されていない場合は、useEffect の 2 番目のオプション パラメータとして配列を渡すことで、エフェクトの呼び出しをスキップするように React に指示できます。以下に示すように、2 回のレンダリング間で count 値が変更されていない場合は、2 回目のレンダリング後にエフェクトがスキップされます。 使用効果(() => { document.title = `${count} 回クリックしました`; }, [count]); // countが変更された場合にのみ更新する 5.componentDidMountをシミュレートするエフェクトを 1 回だけ (コンポーネントがマウントおよびアンマウントされたときのみ) 実行する場合は、次に示すように、2 番目のパラメーターとして空の配列 ([]) を渡すことができます。原理は、ポイント 4 のパフォーマンス最適化で説明したものと同じです。 使用効果(() => { ..... }, []); 6. ベストプラクティスエフェクトの外部の関数がどのプロパティと状態を使用するかを覚えておくのは難しい場合があります。そのため、通常はエフェクト内で必要な関数を宣言する必要があります。 // 悪い、推奨されない関数 Example({ someProp }) { 関数doSomething() { コンソールにログ出力します。 } 使用効果(() => { 何かを実行します(); }, []); // 🔴 これは安全ではありません(`someProp` を使用する `doSomething` を呼び出します) } // 良い、推奨される関数 Example({ someProp }) { 使用効果(() => { 関数doSomething() { コンソールにログ出力します。 } 何かを実行します(); }, [someProp]); // ✅ 安全(このエフェクトでは `someProp` のみを使用します) } 何らかの理由で関数をエフェクトに移動できない場合は、他にいくつかのオプションがあります。
eslint-plugin-react-hooks の exhaustive-deps ルールを有効にすることをお勧めします。これにより、誤った依存関係を追加するときに警告が発行され、修復の提案が提供されます。 // 1. プラグインをインストールする npm i eslint-plugin-react-hooks --save-dev // 2. eslint 設定 { 「プラグイン」: [ // ... 「反応フック」 ]、 「ルール」: { // ... "react-hooks/rules-of-hooks": "エラー", "react-hooks/exhaustive-deps": "警告" } } 7. 重要なポイント(1) useEffectフックは、componentDidMount、componentDidUpdate、componentWillUnmountの組み合わせと考えることができます。 3. コンテキストを使用する複数レベルのデータ転送を処理するために使用されるメソッド。前のコンポーネント ツリーでは、クロスレベルの祖先コンポーネントが孫コンポーネントにデータを渡す場合、レイヤーごとにプロパティを渡すだけでなく、React Context API を使用してこれを行うこともできます。使用例は以下のとおりです。(1) React Context APIを使用してコンポーネントの外部にコンテキストを作成する 'react' から React をインポートします。 テーマコンテキストを React.createContext(0); デフォルトの ThemeContext をエクスポートします。 (2)Context.Providerを使用して、子コンポーネントで共有できるContextオブジェクトを提供する React をインポートし、{useState} を 'react' から取得します。 './ThemeContext' から ThemeContext をインポートします。 './ContextComponent1' から ContextComponent1 をインポートします。 関数ContextPage(){ 定数[count, setCount] = useState(1); 戻る ( <div className="アプリ"> <ThemeContext.Provider 値 = {count}> <コンテキストコンポーネント1 /> </テーマコンテキスト.プロバイダー> <ボタンのクリック時={() => setCount(count + 1)}> クリックしてください </ボタン> </div> ); } デフォルトのContextPageをエクスポートします。 (3)useContext()フック関数はContextオブジェクトを導入し、その値を取得するために使用される。 // サブコンポーネント、サブコンポーネント内の孫コンポーネントを使用します import React from 'react'; './ContextComponent2' から ContextComponent2 をインポートします。 関数ContextComponent(){ 戻る ( <コンテキストコンポーネント2 /> ); } デフォルトのContextComponentをエクスポートします。 // 孫コンポーネント。孫コンポーネントで Context オブジェクトの値を使用します。import React, { useContext } from 'react'; './ThemeContext' から ThemeContext をインポートします。 関数ContextComponent(){ 定数値 = useContext(ThemeContext); 戻る ( <div>useContext:{値}</div> ); } デフォルトのContextComponentをエクスポートします。 4. リデューサーを使用する1. 基本的な使い方useState がより適しているシナリオ: たとえば、状態ロジックの処理が複雑で複数のサブ値が含まれている場合や、次の状態が前の状態に依存する場合など。以下に例を示します。 React をインポートし、 'react' から { useReducer } を追加します。 インターフェース状態タイプ{ カウント: 数 } インターフェースアクションタイプ{ タイプ: 文字列 } 定数初期状態 = { カウント: 0 }; const リデューサー = (状態:状態タイプ、アクション:アクションタイプ) => { スイッチ(アクションタイプ){ ケース '増分': 戻り値: state.count + 1 }; ケース '減少': 戻り値: state.count - 1 }; デフォルト: 新しい Error() をスローします。 } }; 定数UseReducer = () => { const [状態、ディスパッチ] = useReducer(リデューサー、初期状態); 戻る ( <div className="アプリ"> <div>useReducer カウント:{state.count}</div> <button onClick={() => { dispatch({ type: 'decrement' }); }}>useReducer の削減</button> <button onClick={() => { dispatch({ type: 'increment' }); }}>useReducer increase</button> </div> ); }; デフォルトのUseReducerをエクスポートします。 2. 状態の遅延初期化インターフェース状態タイプ{ カウント: 数 } インターフェースアクションタイプ{ タイプ: 文字列、 ペイロード?: 番号 } 定数initCount = 0 定数 init = (initCount:数値)=>{ {count:initCount} を返す } const リデューサー = (状態:状態タイプ、アクション:アクションタイプ)=>{ スイッチ(アクション.type){ ケース '増分': {count: state.count + 1} を返します ケース '減少': {count: state.count - 1} を返します ケース 'リセット': init(action.paylod || 0) を返します デフォルト: 新しい Error() をスローします。 } } 定数UseReducer = () => { const [状態、ディスパッチ] = useReducer(reducer、initCount、init) 戻る ( <div className="アプリ"> <div>useReducer カウント:{state.count}</div> <button onClick={()=>{dispatch({type:'decrement'})}}>useReducer の Reduce</button> <button onClick={()=>{dispatch({type:'increment'})}}>useReducer 増加</button> <button onClick={()=>{dispatch({type:'reset',paylod:10 })}}>useReducer の追加</button> </div> ); } デフォルトのUseReducerをエクスポートします。 5. メモ以下に示すように、親コンポーネントが再レンダリングされると、子コンポーネントのプロパティと状態が変更されていなくても、子コンポーネントも再レンダリングされます。 // 子コンポーネント const ChildComp = () => { console.log('ChildComp...'); 戻り値: (<div>ChildComp...</div>); }; // 親コンポーネント const Parent = () => { 定数[count, setCount] = useState(0); 戻る ( <div className="アプリ"> <div>こんにちは世界{count}</div> <div onClick={() => { setCount(count => count + 1); }}>クリックして増加</div> <チャイルドコンプ/> </div> ); }; デフォルトの親をエクスポートします。 改善: 上記の問題を解決するためにメモ パッケージを使用できますが、親コンポーネントが子コンポーネントにパラメータを渡さず、親コンポーネントが子コンポーネントに単純な型のパラメータ (文字列、数値、ブール値など) を渡す状況のみを解決します。複雑なプロパティが渡される場合は、useCallback (コールバック イベント) または useMemo (複雑なプロパティ) を使用する必要があります。 // 子コンポーネント const ChildComp = () => { console.log('ChildComp...'); 戻り値: (<div>ChildComp...</div>); }; 定数 MemoChildComp = memo(ChildComp); 6.メモを使う次のシナリオを想定します: 親コンポーネントは、子コンポーネントを呼び出すときに、情報オブジェクト プロパティを渡します。親コンポーネント ボタンをクリックすると、コンソールにはレンダリングされる子コンポーネントに関する情報が出力されます。 React をインポートします。{ memo, useState } から 'react'; // 子コンポーネント const ChildComp = (info:{info:{name: string, age: number}}) => { console.log('ChildComp...'); 戻り値: (<div>ChildComp...</div>); }; 定数 MemoChildComp = memo(ChildComp); // 親コンポーネント const Parent = () => { 定数[count, setCount] = useState(0); const [名前] = useState('jack'); 定数[年齢] = useState(11); const info = { 名前、 年齢 }; 戻る ( <div className="アプリ"> <div>こんにちは世界{count}</div> <div onClick={() => { setCount(count => count + 1); }}>クリックして増加</div> <MemoChildComp 情報 = {情報} /> </div> ); }; デフォルトの親をエクスポートします。 理由の分析:
解決する: オブジェクト属性をラップするには、useMemo を使用します。useMemo には 2 つのパラメータがあります。
'react' から React、{ memo、useMemo、useState } をインポートします。 // 子コンポーネント const ChildComp = (info:{info:{name: string, age: number}}) => { console.log('ChildComp...'); 戻り値: (<div>ChildComp...</div>); }; 定数 MemoChildComp = memo(ChildComp); // 親コンポーネント const Parent = () => { 定数[count, setCount] = useState(0); const [名前] = useState('jack'); 定数[年齢] = useState(11); // オブジェクトのプロパティをラップするには useMemo を使用します const info = useMemo(() => ({ name, age }), [name, age]); 戻る ( <div className="アプリ"> <div>こんにちは世界{count}</div> <div onClick={() => { setCount(count => count + 1); }}>クリックして増加</div> <MemoChildComp 情報 = {情報} /> </div> ); }; デフォルトの親をエクスポートします。 7.コールバックを使用する第 6 章の例を続けて、次に示すように、子コンポーネントにイベントを渡す必要があるとします。親コンポーネント ボタンをクリックすると、レンダリングされている子コンポーネントに関する情報がコンソールに出力され、子コンポーネントが再レンダリングされたことが示されます。 'react' から React、{ memo、useMemo、useState } をインポートします。 // 子コンポーネント const ChildComp = (props:any) => { console.log('ChildComp...'); 戻り値: (<div>ChildComp...</div>); }; 定数 MemoChildComp = memo(ChildComp); // 親コンポーネント const Parent = () => { 定数[count, setCount] = useState(0); const [名前] = useState('jack'); 定数[年齢] = useState(11); const info = useMemo(() => ({ 名前、年齢 }), [名前、年齢]); 定数changeName = () => { console.log('出力名...'); }; 戻る ( <div className="アプリ"> <div>こんにちは世界{count}</div> <div onClick={() => { setCount(count => count + 1); }}>クリックして増加</div> <MemoChildComp 情報={情報} 変更名={変更名}/> </div> ); }; デフォルトの親をエクスポートします。 理由を分析します。
解決する: 'react' から React、{ memo、useCallback、useMemo、useState } をインポートします。 // 子コンポーネント const ChildComp = (props:any) => { console.log('ChildComp...'); 戻り値: (<div>ChildComp...</div>); }; 定数 MemoChildComp = memo(ChildComp); // 親コンポーネント const Parent = () => { 定数[count, setCount] = useState(0); const [名前] = useState('jack'); 定数[年齢] = useState(11); const info = useMemo(() => ({ name, age }), [name, age]); 定数changeName = useCallback(() => { console.log('出力名...'); }, []); 戻る ( <div className="アプリ"> <div>こんにちは世界{count}</div> <div onClick={() => { setCount(count => count + 1); }}>クリックして増加</div> <MemoChildComp 情報={情報} 変更名={変更名}/> </div> ); }; デフォルトの親をエクスポートします。 8. 使用Ref useRef の使用シナリオは次の 2 つです。 1. DOM要素を指す以下に示すように、useRef を使用して作成された変数は入力要素を指し、ページがレンダリングされた後に入力にフォーカスします。 'react' から React をインポートします。{useRef、useEffect}。 定数 Page1 = () => { const myRef = useRef<HTMLInputElement>(null); 使用効果(() => { myRef?.current?.focus(); }); 戻る ( <div> <span>使用参照:</span> <input ref={myRef} タイプ="text"/> </div> ); }; デフォルトのページ1をエクスポートします。 2. 変数の保存公式ウェブサイトが言うように、React Hook での useRef の役割は変数のようなもので、これと似たもので、ボックスのようなもので、何でも保存できます。createRef はレンダリングするたびに新しい参照を返しますが、useRef は毎回同じ参照を返します。次の例をご覧ください。 'react' から React、{useRef、useEffect、useState } をインポートします。 定数 Page1 = () => { 定数 myRef2 = useRef(0); 定数[count, setCount] = useState(0) 使用効果(()=>{ myRef2.current = カウント; }); 関数handleClick(){ タイムアウトを設定します(()=>{ console.log(カウント); // 3 コンソールログ(myRef2.current); // 6 },3000) } 戻る ( <div> <div onClick={()=> setCount(count+1)}>クリック数</div> <div onClick={()=> handleClick()}>表示</div> </div> ); } デフォルトのページ1をエクスポートします。 9. 命令型ハンドルを使用する使用シナリオ: DOM ノード全体は ref を通じて取得され、useImperativeHandle を使用して、DOM ノード全体ではなく一部のメソッドとプロパティのみの公開を制御できます。 10.レイアウト効果を使用するその関数シグネチャは useEffect と同じですが、すべての DOM の変更後に同期的にエフェクトを呼び出すため、ここでは示されていません。 useLayoutEffect は、通常記述する Class コンポーネントの componentDidMount および componentDidUpdate と同時に実行されます。 要約するこの記事では、使用シナリオに基づいた例を示し、React Hooks のほとんどの機能を理解して上手に使用できるようにします。 これで、React Hooksの一般的なシナリオの使用に関する記事(要約)は終了です。React Hooksの一般的なシナリオに関連するその他のコンテンツについては、123WORDPRESS.COMの以前の記事を検索するか、次の関連記事を引き続き参照してください。今後とも123WORDPRESS.COMをよろしくお願いいたします。 以下もご興味があるかもしれません:
|
<<: DOSBox を起動後に自動的にコマンドを実行する方法
>>: mysql 解凍パッケージの基本インストールチュートリアル
この記事では、シンプルな HTML ビデオ プレーヤーを実装する方法を紹介し、皆さんと共有します。詳...
この記事の例では、登録とログインの効果を実現するためのVUEの具体的なコードを紹介します。具体的な内...
この記事では、例を使用して、MySQL のデータベース間トランザクション XA 操作について説明しま...
間違った mysql コマンドを入力したのでキャンセルしたいです。どうすればいいですか? ctrl ...
最新のソリューション: -v /usr/share/zoneinfo/Asia/Shanghai:/...
序文MySQL 8.0 の最新バージョンは 8.0.4 rc であり、正式版は近日中にリリースされる...
序文ブラウザをどのようにズームしても、ボックス コンテナーの高さを常に 100% に保つ必要がある場...
Docker はますます成熟し、その機能もますます強力になっています。 Docker Stack を...
かなり前の記事で、 -webkit-box-reflectプロパティについて説明しました。リフレクシ...
目次1. 基本理論1.1 取引1.2 分散トランザクション2. 分散トランザクションソリューション2...
面接の質問で、3 行 3 列のレイアウトが求められます。1 行目の 2 番目の列と 2 行目の 2 ...
序文MySQL の日常的な開発やメンテナンスでは、パスワードの紛失やテーブルの破損など、避けられない...
Linuxでユーザーが所属するグループを変更する1. ユーザーのグループを設定する usermod ...
1. 原因: SQL ファイルをインポートする必要があるのですが、インポートできません。この文を実行...
無線インタラクションにずっと興味があったので、今回は実践してみようと思います〜この分析と評価は iO...