ホームページ > 記事 > ウェブフロントエンド > [翻訳] カスタムフックを使用した React コンポーネントのリファクタリング
React 関数コンポーネントについてよく話され、関数コンポーネントは必然的に大きくなり、より複雑なロジックになるという話を聞きます。結局のところ、コンポーネントを「関数」で記述したため、コンポーネントが拡張され、関数も拡張し続けることを受け入れる必要があります。これは React コンポーネントでも説明されています。
関数コンポーネントでできることはますます増えているため、コード ベース内の関数コンポーネントは全体的にどんどん長くなります。 [関連する推奨事項: Redis ビデオ チュートリアル 、プログラミング ビデオ ]
また、次のことを行う必要があるとも述べられています。抽象化を時期尚早に追加することを避ける
CodeScene を使用している場合、関数が長すぎるか複雑すぎる場合に警告が表示されることに気づくかもしれません。前述の内容に従う場合は、CodeScene 関連の警告をより広範囲に設定する必要があるかどうかを検討する可能性があります。もちろんこれを行うこともできますが、私はこれをすべきではないと思いますし、コードに多くの抽象化を追加することを拒否すべきではありません。それによって多くのメリットが得られますが、ほとんどの場合、コストはかかりません。高い。コードの健全性を引き続き非常に良好に保つことができます。
複雑さへの対処
useEffect、またはその他のフックと同様、サブコンポーネント自体も関数です。したがって、同じ考え方を自然に使用して、関数コンポーネントの複雑さに対処できます。
新しい関数を作成することで、公開パターンに準拠した複雑なコードをカプセル化できます。
複雑なコンポーネントを処理するより一般的な方法は、コンポーネントを複数のサブコンポーネントに分解することです。ただし、そうすると不自然に感じられたり、これらのサブコンポーネントを正確に説明することが難しくなる場合があります。このとき、コンポーネントのフック関数のロジックを整理することで、新たな抽象点を発見することができます。
useState
、useEffect、またはその他の組み込みフック関数の長いリストが表示されるたびに、それらをカスタム ファイルに抽出できるかどうかを検討する必要があります。針。カスタムフック関数は、その中で他のフック関数を利用できる関数であり、カスタムフック関数の作成も簡単です。
以下に示すコンポーネントはダッシュボードに相当し、リストを使用してユーザー ウェアハウス (github に似たものを想像してください) のデータを表示します。このコンポーネントは複雑なコンポーネントではありませんが、カスタム フックを適用する方法の良い例です。
function Dashboard() { const [repos, setRepos] = useState<Repo[]>([]); const [isLoadingRepos, setIsLoadingRepos] = useState(true); const [repoError, setRepoError] = useState<string | null>(null); useEffect(() => { fetchRepos() .then((p) => setRepos(p)) .catch((err) => setRepoError(err)) .finally(() => setIsLoadingRepos(false)); }, []); return ( <div className="flex gap-2 mb-8"> {isLoadingRepos && <Spinner />} {repoError && <span>{repoError}</span>} {repos.map((r) => ( <RepoCard key={i.name} item={r} /> ))} </div> ); }フック ロジックをカスタム フックに抽出します。このコードを
use
で始まる関数にコピーするだけです (ここではuseRepos# と名前を付けます) ##): <pre class="brush:js;toolbar:false;">/**
* 请求所有仓库用户列表的hook函数
*/
export function useRepos() {
const [repos, setRepos] = useState<Repo[]>([]);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
fetchRepos()
.then((p) => setRepos(p))
.catch((err) => setError(err))
.finally(() => setIsLoading(false));
}, []);
return [repos, isLoading, error] as const;
}</pre>
が use
で始まる必要がある理由は、
プラグインが現在作成しているものがフック関数であることを検出できるためです。これにより、プラグインはフック関数がカスタム フックの正しい 関連ルール
に準拠しているかどうかをチェックできます。 リファイン前と比較して、リファイン後に新たに現れたのは、return ステートメント と
だけです。ここでの型ヒントは、型推論が正しいことを確認するためのものです: 3 つの要素を含む配列、型は Repo[]、boolean、string | null です。もちろん、フック関数から望むものを返すことができます。 翻訳者注: ここに
as const
as constを追加しない場合、推論される型は
をコンポーネントに適用すると、コードは次のようになります。(string | boolean | Repo[] | null)[]
です。追加後の推論される型はreadonly [Repo[] 、ブール値、文字列 | null]
。カスタム フック
useRepos
function Dashboard() { const [repos, isLoadingRepos, repoError] = useRepos(); return ( <div className="flex gap-2 mb-8"> {isLoadingRepos && <Spinner />} {repoError && <span>{repoError}</span>} {repos.map((i) => ( <RepoCard key={i.name} item={i} /> ))} </div> ); }
現在、コンポーネント内で何も呼び出すことができないことがわかります。 setter
関数は、状態を変更できないことを意味します。このコンポーネントでは、状態を変更するためのロジックを含める必要はなくなりました。これらのロジックは
フック関数に含まれています。もちろん、本当に必要な場合は、フック関数の return ステートメントで公開できます。 これを行うことでどのようなメリットがあるのでしょうか? React のドキュメントには次のように記載されています:
このアプリケーションの他のコンポーネントもウェアハウス内のユーザー リストを表示する必要がある場合、このコンポーネントが行う必要があるのは、useRepos
フック関数をインポートすることだけであると簡単に想像できます。おそらく何らかの形式のキャッシュを使用してフックが更新される場合、またはポーリングまたはより複雑なアプローチによって継続的に更新される場合、このフックを参照するすべてのコンポーネントが恩恵を受けます。
もちろん、カスタム フックの抽出には、再利用が容易になるだけでなく、他の利点もあります。この例では、すべての useState
と useEffect
は同じ機能、つまりライブラリ ユーザー リストを取得することを目的としています。これをアトミック関数とみなします。コンポーネントには、そのようなアトミック関数を多数含めることができます。これらのアトミック関数のコードを別のカスタム フック関数に抽出すると、コード ロジックを変更するときにどの状態を同期的に更新する必要があるかを見つけることが容易になり、見逃される可能性が低くなります。さらに、これを行うことの利点は次のとおりです。
useState や
useEffect などのプロジェクトに簡単に適用できます。 Dan Abramov の
useInterval フックは一例です。たとえば、
useRepos に似たフックがありますが、更新をポーリングできる必要があるとします。次に、フックで
useInterval を使用してみてください。
英語の元のアドレス: https://codescene.com/engineering-blog/refactoring-components-in-react-with-custom-hooks[推奨学習] :
JavaScript ビデオ チュートリアル ]
以上が[翻訳] カスタムフックを使用した React コンポーネントのリファクタリングの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。