問題コードuseEffectによって発生したクロージャの問題コードを見てみましょう 定数 btn = useRef(); const [v, setV] = useState(''); 使用効果(() => { クリックハンドルを () とします => { コンソールにログ出力します。 } btn.current.addEventListener('click', clickHandle) 戻り値 () => { btn.removeEventListener('click', clickHandle) } }, []); 定数入力ハンドル = e => { setV(e.target.value) } 戻る ( <> <入力値={v} onChange={inputHandle} /> <button ref={btn} >テスト</button> </> ) useEffect の依存関係配列は空なので、内部コードはページのレンダリングが完了した後に 1 回だけ実行され、ページが破棄されたときにもう一度実行されます。このとき、入力ボックスに任意の文字を入力してテスト ボタンをクリックすると、出力は空になります。その後、どのような文字を入力して再度テスト ボタンをクリックしても、出力結果は空のままです。 なぜこのようなことが起こるのでしょうか?実際、それは閉鎖によって引き起こされます。 原因関数のスコープは、関数が定義されるときに決定されます。 btn のクリック イベントを登録する場合、スコープは次のようになります。 現時点では、アクセス可能な自由変数 v はまだ null です。クリックイベントがトリガーされると、クリックコールバック関数が実行されます。このとき、まず実行コンテキストが作成され、スコープチェーンが実行コンテキストにコピーされます。
シーンを生成する
解決この閉鎖問題に対する 5 つの解決策は次のとおりです。 1. 代入によってvを直接変更し、vを変更するメソッドをuseCallbackでラップする v を変更するメソッドを useCallback でラップします。useCallback でラップされた関数はキャッシュされます。依存関係の配列が空なので、ここで直接割り当てによって変更された v は古い v です。setState は状態を変更する公式に推奨される方法であるため、この方法は推奨されません。ここでは、setV は再レンダリングをトリガーするためだけに使用されています。 // 直接変更しやすいように、v の宣言を const から var に変更します。var [v, setV] = useState(''); const inputHandle = useCallback(e => { {値} = e.targetとする v = 値 setV(値) }, []) 2. useEffectの依存関係にvを追加する これは、ほとんどの人が最初に思いつく解決策かもしれません。v は古いので、v が更新されるたびにイベントを再登録すればいいのではないでしょうか。しかし、これでは v が更新されるたびに再登録が必要になります。理論上は、1 回だけ登録すればよいイベントが複数回登録されることになります。 3. vの再宣言を避ける let または var を使用して v の代わりに変数を宣言し、setState 関連関数を使用してレンダリングをトリガーする代わりに、変数を直接変更します。この方法では、変数は再宣言されず、クリック コールバック関数で「最新の」値を取得できます。ただし、この方法は推奨されません。この例では、再レンダリングがないため、入力コンポーネントには常に空の値が表示され、期待される操作を満たしていません。 4. useStateの代わりにuseRefを使用する 定数 btn = useRef(); 定数vRef = useRef(''); 定数[v, setV] = useStat(''); 使用効果(() => { クリックハンドルを () とします => { console.log('v:', vRef.current); } btn.current.addEventListener('click', clickHandle) 戻り値 () => { btn.removeEventListener('click', clickHandle) } }, []); 定数入力ハンドル = e => { {値} = e.targetとする vRef.current = 値 setV(値) } 戻る ( <> <入力値={v} onChange={inputHandle} /> <button ref={btn} >テスト</button> </> ) useRef ソリューションが効果的な理由は、入力の変更ごとに vRef オブジェクトの現在のプロパティが変更され、vRef は再レンダリングされても常にその vRef であるためです。vRef はオブジェクトであるため、スタック メモリに格納されている変数の値はヒープ メモリ内のオブジェクトのアドレスであり、単なる参照です。オブジェクトの特定のプロパティのみが変更され、参照は変更されません。クリックイベントのスコープチェーンは常に同じvRefにアクセスします 5. vをオブジェクト型に置き換える 実際、useRef を使用する場合と同様に、オブジェクトである限り、特定の属性のみを変更しても、状態が指すアドレスは変更されません。 コードアドレステストコードを見るにはここをクリックしてください これで、React useEffect クロージャの落とし穴に関するこの記事は終わりです。React useEffect クロージャに関するより関連性の高いコンテンツについては、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。 以下もご興味があるかもしれません:
|
<<: Linux が Sudo 権限昇格の脆弱性を公開、どのユーザーでも root コマンドを実行可能
実装のアイデアまず、親コンテナーを作成し、2 つの順序なしリストを使用して、柔軟なレイアウトで親コン...
目次DockerのインストールNvidia-docker のインストールDockerのインストール1...
1. ディスプレイボックス;要素にこのプロパティを設定すると、display:inline-bloc...
1. 問題の説明何らかの理由により、中国でのDockerイメージのダウンロード速度は特に遅くなります...
今日は、マスタースレーブ遅延が発生する理由とその対処方法について説明します。しっかり座って出発の準備...
目次背景問題の場所さらなる分析要約する背景私のコース「Vue 3 エンタープライズレベルの音楽アプリ...
ソフトウェア パッケージが存在しない場合は、インストールされているソフトウェアのソフトウェア ソース...
コンテナをソートするためにdepends_onを使用しても、コンテナ間の依存関係の問題は完全には解決...
この記事では、タブバーの切り替えコンテンツバーを簡単に実現するためのJavaScriptの具体的なコ...
以前はMySQLをあまり使用していなかったため、MySQLの機能にあまり詳しくありませんでした。この...
目次Reactの公式サイトではライフサイクルの説明を見ることができます次に、ネストされたコンポーネン...
SSHとは何か管理者はリモートでログインして、インターネット経由で接続されたさまざまな場所にある複数...
1. 参照整合性参照整合性とは、主に外部キー制約を使用した複数のテーブル間の設計を指します。複数テ...
概要Nginx ロード バランシングは、アップストリーム サーバー (実際のビジネス ロジックによっ...
ステップ1: システムのアーキテクチャを確認する dpkg --print-architecture...