フックを使用して React コンポーネントを書くときに注意すべき 5 つの点

フックを使用して React コンポーネントを書くときに注意すべき 5 つの点

Hook は React16.8 で追加された新しい機能です。 React の公式ドキュメントでは React フックの関連概念について説明されていますが、公式ドキュメントを読むだけではフックをうまく使いこなすのは難しく、フックを書く際に罠やエラーに陥りやすいです。この記事では5つの悪い場所をまとめています。

01. レンダリングが不要な場合はuseStateを使用する

関数コンポーネントでは、 useStateを使用して状態を管理できます。これにより、状態管理が非常に簡単になりますが、悪用される可能性も高くなります。次のコードサンプルを通じて、見落とされやすい領域を確認してみましょう。

非推奨×

関数 ClickButton(props){
 定数[count, setCount] = setState(0)
 定数onClickCount = () => {
  setCount((c) => c + 1)
 }
 定数onClickRequest = () => {
  apiCall(カウント)
 }
 
 戻る (
  <div>
   <button onClick={onClickCount}>クリック</button>
   <button onClick={onClickRequest}>送信</button>
  </div>
 )
}

問題: 上記のコードをよく見ると、一見何も問題はありません。ボタンをクリックすると、 countが更新されます。しかし、問題はここにあります。 return 部分はcount状態を使用しておらず、 setCountごとにコンポーネントが 1 回再レンダリングされますが、これは必要なことではありません。 余分なレンダリングによってページのパフォーマンスが悪化するため、次のようにコードを変更します。

推奨√
コンポーネント宣言サイクル中に保存できる変数だけが必要で、変数の更新でコンポーネントを再レンダリングする必要がない場合は、 useRefフックを使用できます。

関数 ClickButton(props){
 定数カウント = useRef(0)
 定数onClickCount = () => {
  count.current++
 }
 定数onClickRequest = () => {
  apiCall(カウント.現在)
 }

 戻る (
  <div>
   <button onClick={onClickCount}>クリック</button>
   <button onClick={onClickRequest}>送信</button>
  </div>
 )
}

02. リンクの代わりにrouter.pushを使用する

React SPA アプリケーションでは、 react-routerを使用してルート ジャンプを処理します。多くの場合、次のコードに示すように、コンポーネントにボタンを記述し、ボタン イベントをクリックしてルート ジャンプを処理します。

非推奨×

関数 ClickButton(props){
 定数履歴 = useHistory()
 定数onClickGo = () => {
  history.push('/where-page')
 }
 戻る <button onClick={onClickGo}>どこへ移動する</button>
}

問題: 上記のコードは機能しますが、アクセシビリティの要件を満たしていません。ボタンはスクリーン リーダーによってリンクとして認識されません。したがって、コードを次のように変換できます。

推奨√

関数 ClickButton(props){
 戻る <Link to="/next-page">
  <span>どこへ行く</span>
 </リンク>
}

03. useEffectでアクションを処理する

場合によっては、React が DOM を更新した後に、追加のコードを実行したいことがあります。たとえば、ネットワーク リクエストの送信、DOM の手動変更、ログの記録などです。

非推奨×

関数 DataList({ onSuccess }) {
 const [ロード中、setLoading] = useState(false);
 定数[エラー、setError] = useState(null);
 const [データ、setData] = useState(null);

 定数フェッチデータ = () => {
  読み込みをtrueに設定します。
  呼び出しAPI()
   .then((res) => setData(res))
   .catch((err) => setError(err))
   .finally(() => setLoading(false));
 };

 使用効果(() => {
  フェッチデータ();
 }, []);

 使用効果(() => {
  if (!ロード中 && !エラー && データ) {
   成功の場合();
  }
 }, [読み込み中、エラー、データ、onSuccess]);

 <div>データ: {data}</div> を返します。
}

問題: 上記のコードでは 2 つのuseEffectが使用されています。最初の useEffects は非同期データを要求するために使用され、2 番目の useEffects はコールバック関数を呼び出すために使用されます。 2 番目のuseEffectの実行は、最初の非同期リクエスト データが成功した場合にのみトリガーされます。ただし、2 番目のuseEffectの依存関係が最初のuseEffectの成功したリクエスト データによって完全に制御されることを完全に保証することはできません。したがって、コードを次のように変換できます。

推奨√

関数 DataList({ onSuccess }) {
 const [ロード中、setLoading] = useState(false);
 定数[エラー、setError] = useState(null);
 const [データ、setData] = useState(null);

 定数フェッチデータ = () => {
  読み込みをtrueに設定します。
  呼び出しAPI()
   .then((res) => {
    データ設定(res)
    成功時()
    })
   .catch((err) => setError(err))
   .finally(() => setLoading(false));
 };

 使用効果(() => {
  フェッチデータ();
 }, []);
 <div>データ: {data}</div> を返します。
}

04. 単一責任コンポーネント

コンポーネントを複数の小さなコンポーネントに分割する必要があるのはいつですか?コンポーネントツリーを構築するにはどうすればいいですか?これらすべての問題は、コンポーネントベースのフレームワークを使用するときに毎日発生します。ただし、コンポーネントを設計するときによくある間違いは、2 つのユースケースを 1 つのコンポーネントに結合することです。

非推奨×

関数 Header({ menuItems }) {
 戻る (
  <ヘッダー>
   <ヘッダー内部メニュー項目={メニュー項目} />
  </ヘッダー>
 );
}

関数 HeaderInner({ menuItems }) {
 isMobile() を返します? <BurgerButton menuItems={menuItems} /> : <Tabs tabData={menuItems} />;
}

問題: このアプローチでは、 HeaderInnerコンポーネントは同時に 2 つの異なる機能を実行しようとします。一度に複数の機能を実行するのは理想的ではありません。さらに、コンポーネントを他の場所でテストしたり再利用したりすることが難しくなります。したがって、コードを次のように変換できます。

推奨√

条件を 1 レベル上に移動すると、コンポーネントの目的がわかりやすくなり、同時に 2 つの異なることを行おうとするのではなく、コンポーネントが<Tabs/>または<BurgerButton/>のいずれか 1 つの責任のみを持つようになります。

関数 Header(props) {
 戻る (
  <ヘッダー>
   {isMobile() ? <BurgerButton menuItems={menuItems} /> : <Tabs tabData={menuItems} />}}
  </ヘッダー>
 )
}

05. 単一責任の使用効果

componentWillReceivePropscomponentDidUpdateメソッドを比較することで、 userEffectの素晴らしさに気づきました。ただし、useEffect が適切に使用されていない場合は、問題が発生する可能性があります。

非推奨×

関数の例(props) {
 定数 location = useLocation();
 定数フェッチデータ = () => {
  /* API を呼び出す */
 };

 const updateBreadcrumbs = () => {
  /* パンくずリストを更新しています */
 };

 使用効果(() => {
  フェッチデータ();
  パンくずリストを更新します。
 }, [location.pathname]);

 戻る (
  <div>
   <パンくず />
  </div>
 );
}

問題: 上記のuseEffect同時に 2 つの副作用をトリガーしますが、それらすべてが必要な副作用ではないため、次のようにコードを変更できます。

推奨√

1 つの useEffect から 2 つの副作用を分離します。

関数の例(props) {
 定数 location = useLocation();

 定数フェッチデータ = () => {
  /* API を呼び出す */
 };

 const updateBreadcrumbs = () => {
  /* パンくずリストを更新しています */
 };

 使用効果(() => {
  フェッチデータ();
  パンくずリストを更新します。
 }, [location.pathname]);

 戻る (
  <div>
   <パンくず />
  </div>
 );
}

参照:

2020 年に React コンポーネント (フック付き) を書くときによくある 5 つの間違い

以上が、Reactコンポーネントを記述する際にフックを使用する際に注意すべき5つのポイントの詳細です。Reactコンポーネントを記述する際のフックの詳細については、123WORDPRESS.COMの他の関連記事にも注目してください!

以下もご興味があるかもしれません:
  • Reactフックの長所と短所
  • React Hooks の一般的な使用シナリオ (概要)
  • Reactフック入門チュートリアル
  • Reactフックとzarmコンポーネントライブラリ構成に基づいてh5フォームページを開発するためのサンプルコード
  • Reactはフックを使用して、制御されたコンポーネントの状態バインディングを簡素化します。
  • 今年最もエキサイティングな React の新機能、React Hooks を 30 分でマスターする
  • 完全なReact Hooksの練習を記録する
  • React Hooksの深い理解と使用
  • Reactフックの仕組み

<<:  Nginx 静的サービス設定の詳細な説明 (ルートとエイリアスの指示)

>>:  Linux での MySQL 5.6.27 インストール チュートリアル

推薦する

MySQL 分離レベルの詳細な説明と例

目次MySQL の 4 つの分離レベルデータ テーブルを作成します。分離レベルの設定物事の分離レベル...

WeChatアプレットを少なく使う方法(最適な方法)

序文私は less/sass を書くことに慣れていますが、小さなプログラムを開発するときには、まだ ...

JQueryはアニメーション効果の非表示と表示を実装します

この記事では、アニメーション効果の非表示と表示を実現するためのJQueryの具体的なコードを参考まで...

HTML の基本 - CSS スタイルシート、スタイル属性、フォーマット、レイアウトの詳細

1.位置:固定一部の Web サイトの右下隅にあるポップアップ ウィンドウなどの、ブラウザーを基準と...

nginxとバックエンドポート間の競合の解決策

質問: Alice 管理システムを開発しているときに、すべてのバックエンド インターフェイスが最初の...

表 td 画像水平および垂直中央揃えコード

HTMLコード:コードをコピーコードは次のとおりです。 <td align="cen...

Windows 10 に TomCat をインストールするチュートリアル図

WindowsにTomCatをインストールするこの記事では、WindowsプラットフォームにTomC...

MySQLにおけるrow_numberの実装プロセス

1. 背景一般的に、データ ウェアハウス環境では、row_number 関数を使用して特定のディメン...

1 つの記事で Vuex を理解する

目次概要Vuex の 4 つの主要オブジェクト状態の使用突然変異の使用ゲッターの使用アクションの使用...

Vue3+Vue-cli4 プロジェクトで Tencent スライダー検証コードを使用する方法

導入:従来の画像検証コードと比較して、スライダー検証コードには次の利点があります。サーバーは検証コー...

Vueは視覚的なドラッグページエディタを実装します

目次ドラッグアンドドロップの実装ドラッグイベントドラッグして開始リリースゾーンでの移動境界処理、角度...

スプレッド演算子のサンプルコードと JavaScript での応用

スプレッド演算子を使用すると、式をある時点で展開できます。スプレッド演算子は、複数のパラメーター (...

HTMLページでよく使われるいくつかの小さなメソッド

<Head>タグに追加する<meta http-equiv="pragm...

vue.js パッケージ化プロジェクトの後の空白ページの解決策

Vueに触れたばかりのパートナーの多くは、開発環境ではVueプロジェクトは正常であるが、パッケージ化...

vue $setは配列コレクションオブジェクトへの値の割り当てを実装します

Vue $set 配列コレクションオブジェクトの割り当てVue カスタム配列オブジェクト コレクショ...