簡潔なReactコンポーネントを書くためのヒント

簡潔なReactコンポーネントを書くためのヒント

この記事は、翻訳された記事「きれいなReactコンポーネントを書くためのシンプルなヒント」に基づいています。元の著者はIskander Samatovです。

この記事では、よりクリーンな React コンポーネントを記述し、プロジェクトをより適切に拡張するのに役立ついくつかの簡単なテクニックを紹介します。

スプレッド演算子を使用してプロパティを渡すのは避けてください

まず、避けるべきアンチパターンから始めましょう。明確な理由がない限り、スプレッド演算子 (例: { ...props }) を使用してコンポーネント ツリーを介して props を渡すことは避けてください。

この方法でプロパティを渡すと、コンポーネントの記述が速くなります。しかし、これによりコード内のバグを見つけることも難しくなります。そうすると、作成したコンポーネントに対する信頼が失われ、コンポーネントのリファクタリングが困難になり、デバッグが困難なバグが発生する可能性があります。

関数パラメータをオブジェクトにカプセル化する

関数が複数のパラメータを受け入れる場合、それらをオブジェクトにカプセル化するのが最適です。例えば:

エクスポートconst sampleFunction = ({ param1, param2, param3 }) => {
  コンソールにログ出力します。
}

このように関数シグネチャを記述することには、いくつかの大きな利点があります。

  1. パラメータが渡される順序を気にする必要がなくなりました。関数パラメータが渡される順序が原因でバグを引き起こすミスをいくつか犯しました。
  2. スマートプロンプトが設定されたエディター(現在ほとんどのエディターに搭載されています)では、関数パラメータの自動補完が非常にうまく実行されます。

イベント処理関数の場合、処理関数を関数の戻り値として使用します。

関数型プログラミングに精通している場合、このプログラミング手法は、いくつかのパラメータが事前に設定されているため、関数のカリー化に似ていることがわかります。

次の例を見てみましょう。

'react' から React をインポートします

デフォルトの関数 SampleComponent({ onValueChange }) をエクスポートします。

  const handleChange = (キー) => {
    戻り値 (e) => onValueChange(キー、e.target.value)
  }

  戻る (
    <フォーム>
      <input onChange={handleChange('name')} />
      <input onChange={handleChange('email')} />
      <input onChange={handleChange('phone')} />
    </フォーム>
  )
}

ご覧のとおり、このようにハンドラー関数を記述すると、コンポーネント ツリーが簡潔になります。

コンポーネントのレンダリングではif/elseの代わりにマップを使用します

カスタム ロジックに基づいてさまざまな要素をレンダリングする必要がある場合は、if/else ステートメントの代わりに map を使用することをお勧めします。

以下は if/else を使用した例です。

'react' から React をインポートします

const Student = ({ name }) => <p>生徒名: {name}</p>
const Teacher = ({ name }) => <p>教師名: {name}</p>
const Guardian = ({ name }) => <p>ガーディアン名: {name}</p>

デフォルト関数 SampleComponent({ user }) をエクスポートします。
  コンポーネントを Student にします。
  if (user.type === '教師') {
    コンポーネント = 教師
  } それ以外の場合 (user.type === 'guardian') {
    コンポーネント = ガーディアン
  }

  戻る (
    <div>
      <コンポーネント名={user.name} />
    </div>
  )
}

以下は map を使用した例です。

'react' から React をインポートします

const Student = ({ name }) => <p>生徒名: {name}</p>
const Teacher = ({ name }) => <p>教師名: {name}</p>
const Guardian = ({ name }) => <p>ガーディアン名: {name}</p>

定数COMPONENT_MAP = {
  学生: 学生、
  先生:先生、
  ガーディアン: ガーディアン
}

デフォルト関数 SampleComponent({ user }) をエクスポートします。
  const コンポーネント = COMPONENT_MAP[user.type]

  戻る (
    <div>
      <コンポーネント名={user.name} />
    </div>
  )
}

この簡単な戦略を使用すると、コンポーネントをより読みやすく、理解しやすくすることができます。また、論理的な拡張も容易になります。

フックコンポーネント

このモードは、悪用されない限り非常に便利です。

アプリケーションでは多くのコンポーネントを使用することになる場合があります。機能するために状態が必要な場合は、その状態を提供するフックでラップできます。これらのコンポーネントの良い例としては、ポップアップ、トースト通知、シンプルなモーダル ダイアログなどがあります。たとえば、単純な確認ダイアログのフック コンポーネントを次に示します。

'react' から React をインポートします。{useCallback、useState }。
'components/global/ConfirmationDialog' から ConfirmationDialog をインポートします。

デフォルト関数 useConfirmationDialog({ をエクスポートする
  ヘッダーテキスト、
  本文、
  確認ボタンテキスト、
  確認クリック時、
}) {
  定数[isOpen, setIsOpen] = useState(false);

  定数 onOpen = () => {
    setIsOpen(true);
  };

  定数ダイアログ = useCallback(
    () => (
      <確認ダイアログ
        ヘッダーテキスト={ヘッダーテキスト}
        本文={本文}
        isOpen={isOpen}
        onConfirmClick={onConfirmClick}
        onCancelClick={() => setIsOpen(false)}
        確認ボタンテキスト={確認ボタンテキスト}
      />
    )、
    [開く]
  );

  戻る {
    ダイアログ、
    オープン時、
  };
}

フック コンポーネントは次のように使用できます。

「react」からReactをインポートします。
'./useConfirmationDialog' から { useConfirmationDialog } をインポートします。

関数クライアント() {
  const { ダイアログ、onOpen } = useConfirmationDialog({
    headerText: "このレコードを削除しますか?"
    本文:
      「このレコードを削除してもよろしいですか? 元に戻すことはできません。」
    確認ボタンテキスト:「削除」、
    onConfirmClick: handleDeleteConfirm、
  });

  関数handleDeleteConfirm() {
    //TODO: 削除
  }

  const handleDeleteClick = () => {
    オープン時();
  };

  戻る (
    <div>
      <ダイアログ />
      <ボタンのonClick={handleDeleteClick} />
    </div>
  );
}

デフォルトのクライアントをエクスポートします。

このようにコンポーネントを抽出すると、状態管理のために大量の定型コードを記述する必要がなくなります。 React フックについて詳しく知りたい場合は、私の投稿をご覧ください。

コンポーネントの分離

次の 3 つのヒントは、コンポーネントを巧みに分割する方法に関するものです。私の経験では、コンポーネントをシンプルに保つことが、プロジェクトを管理しやすくするための最善の方法です。

ラッパーの使用

複雑なコンポーネントを分解する方法を見つけるのに苦労している場合は、コンポーネントの各要素が提供する機能を確認してください。一部の要素は、ドラッグ アンド ドロップなどの独自の機能を提供します。

以下は react-beautiful-dnd を使用してドラッグ アンド ドロップを実装するコンポーネントの例です。

'react' から React をインポートします
'react-beautiful-dnd' から { DragDropContext, Droppable } をインポートします。
デフォルト関数DraggableSample()をエクスポートする{
  関数handleDragStart(結果) { 
    console.log({ 結果 });
  }
  関数handleDragUpdate({ destination }) { 
    console.log({ 宛先 });
  }
  const handleDragEnd = ({ ソース、 宛先 }) => { 
    console.log({ ソース、 宛先 });
  };
  戻る (
    <div>
      <ドラッグドロップコンテキスト
        onDragEnd={handleDragEnd}
        onDragStart={handleDragStart}
        onDragUpdate={handleDragUpdate}
      >
        <ドロップ可能 
          droppableId="ドロップ可能"
          方向="水平"
        >
          {(提供) => (
            <div {...provided.droppableProps} ref={provided.innerRef}> 
              {columns.map((列, インデックス) => {
                戻る (
                  <列コンポーネント
                    キー={インデックス}
                    列={列}
                  />
                );
              })}
            </div>
          )}
        </ドロップ可能>
      </ドラッグドロップコンテキスト>
    </div>
  )
}

次に、すべてのドラッグ ロジックをラッパーに移動した後のコンポーネントを見てみましょう。

'react' から React をインポートします
デフォルト関数DraggableSample()をエクスポートする{
  戻る (
    <div>
      <ドラッグラッパー> 
      {columns.map((列, インデックス) => { 
        戻る (
          <ColumnComponent キー = {インデックス} 列 = {列} />
        );
      })}
      </ドラッグラッパー>
    </div>
  )
}

ラッパーのコードは次のとおりです。

'react' から React をインポートします
'react-beautiful-dnd' から { DragDropContext, Droppable } をインポートします。
デフォルトの関数DragWrapper({children})をエクスポートします。
  関数handleDragStart(結果) { 
    console.log({ 結果 });
  }
  関数handleDragUpdate({ destination }) { 
    console.log({ 宛先 });
  }
  const handleDragEnd = ({ ソース、 宛先 }) => { 
    console.log({ ソース、 宛先 });
  };
  戻る (
    <ドラッグドロップコンテキスト 
      onDragEnd={handleDragEnd}
      onDragStart={handleDragStart} 
      onDragUpdate={handleDragUpdate}
    >
      <ドロップ可能 droppableId="ドロップ可能" direction="水平"> 
        {(提供) => (
          <div {...provided.droppableProps} ref={provided.innerRef}> 
            {子供たち}
          </div>
        )}
      </ドロップ可能>
    </ドラッグドロップコンテキスト>
  )
}

したがって、コンポーネントの機能をより高いレベルで確認する方が直感的になります。ドラッグのすべての機能はラッパー内にあるため、コードを理解しやすくなります。

関心の分離

これは、大きなコンポーネントを分解するための私のお気に入りの方法です。

React の観点から見ると、関心の分離とは、データの取得と変更を担当するコンポーネントの部分と、要素の表示のみを担当する部分を分離することを意味します。

この関心の分離がフックを導入する主な理由です。カスタム フックを使用して、すべてのメソッドまたはグローバル状態に接続されたロジックをカプセル化できます。

たとえば、次のコンポーネントを見てみましょう。

'react' から React をインポートします
'./API' から { someAPICall } をインポートします。 
'./ItemDisplay' から ItemDisplay をインポートします。
デフォルト関数SampleComponent()をエクスポートします。 
  const [データ、setData] = useState([])
  使用効果(() => { 
    someAPICall().then((結果) => { setData(結果)})
  }, [])
  関数 handleDelete() { console.log('削除!'); }
  関数 handleAdd() { console.log('追加!'); }
  const handleEdit = () => { console.log('編集!'); };
  戻る (
    <div>
      <div>
        {data.map(item => <ItemDisplay item={item} />)} 
      </div>
      <div>
        <ボタンのクリック={handleDelete} /> 
        <ボタンのクリック時={handleAdd} /> 
        <ボタン onClick={handleEdit} /> 
      </div>
    </div>
  )
}

以下は、カスタム フックによって分割されたコードを使用したリファクタリングされたバージョンです。

'react' から React をインポートします
'./ItemDisplay' から ItemDisplay をインポートします。
デフォルト関数SampleComponent()をエクスポートします。
  const { データ、handleDelete、handleEdit、handleAdd } = useCustomHook()
  戻る (
    <div>
      <div>
        {data.map(item => <ItemDisplay item={item} />)} 
      </div>
      <div>
        <ボタンのクリック={handleDelete} /> 
        <ボタンのクリック時={handleAdd} /> 
        <ボタン onClick={handleEdit} /> 
      </div>
    </div>
  )
}

フック自体のコードは次のとおりです。

'./API' から { someAPICall } をインポートします。
エクスポートconst useCustomHook = () => { 
  const [データ、setData] = useState([])
  使用効果(() => { 
    someAPICall().then((結果) => { setData(結果)})
  }, [])
  関数 handleDelete() { console.log('削除!'); }
  関数 handleAdd() { console.log('追加!'); }
  const handleEdit = () => { console.log('編集!'); };
  戻り値: { handleEdit、handleAdd、handleDelete、data }
}

各コンポーネントは個別のファイルとしてパッケージ化されています

通常、次のようなコードが書かれます。

'react' から React をインポートします
エクスポートデフォルト関数SampleComponent({データ}) {
  const ItemDisplay = ({名前、日付}) => ( 
    <div>
      <h3>{名前}</h3>
      <p>{日付}</p>
    </div> 
  )
  戻る (
    <div>
      <div>
        {data.map(item => <ItemDisplay item={item} />)}
      </div>
    </div> 
  )
}

React コンポーネントをこのように記述することに問題はありませんが、良い方法ではありません。 ItemDisplay コンポーネントを別のファイルに移動すると、コンポーネントが疎結合になり、拡張しやすくなります。

ほとんどの場合、クリーンで整然としたコードを書くには、適切なパターンに従い、アンチパターンを避けるように注意し、時間をかける必要があります。したがって、時間をかけてこれらのパターンに従うと、クリーンな React コンポーネントを作成するのに役立ちます。これらのパターンは私のプロジェクトで非常に役立っており、皆さんもそう感じていただければ幸いです。

以上が、簡潔なReactコンポーネントを書くためのヒントの詳細です。Reactコンポーネントを書くためのヒントの詳細については、123WORDPRESS.COMの他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • Reactエラー境界コンポーネント処理
  • react setStateの詳細な説明
  • Reactはラジオコンポーネントのサンプルコードを実装します
  • React で setInterval 関数を使用する例
  • Andrew Ng の機械学習演習: SVM サポートベクターマシン

<<:  Dockerはdockerfileを使用してnode.jsアプリケーションを起動します

>>:  mysql 結合クエリ (左結合、右結合、内部結合)

推薦する

JavaScript のスプレッド演算子とレスト演算子の違いの詳細な説明

目次レスト演算子とは何ですか? JavaScript 関数では REST 演算子はどのように機能しま...

Dockerのyumソースの設定とCentOS7へのインストールの詳細な説明

ここではCentOS7が使用されており、カーネルバージョンは [root@localhost ~]#...

Linux でファイルの種類を理解して識別する方法

序文ご存知のとおり、Linux ではハードディスクやグラフィック カードなどすべてがファイルです。 ...

CentOS7 環境での DHCP 設定チュートリアル

目次CentOS7環境での設定コマンド手順1. DHCP設定ファイルを設定する2. グローバル構成を...

2つのVirtualBox仮想ネットワークをブリッジするLinuxブリッジメソッドの手順

この記事は、この時期の「ピーターから奪ってポールに払う」という仕事のスタイルに対する私の不満から生ま...

CSS 3D からソースコードによる空間座標軸へ

かつて、サイコロを振るゲームについて話しました。その時は、steps 属性 + スプライト画像を使用...

div を下から上にスライドさせる CSS3 の例

1. まず、CSS3 のターゲット セレクターを使用し、a タグを使用して id セレクターを指定し...

CentOS 7 に PHP5 用の suPHP をインストールする方法 (Peng Ge)

デフォルトでは、CentOS 7 上の PHP は apache または nobody として実行さ...

Linux における SUID、SGID、SBIT の素晴らしい使い方の詳細な説明

序文Linux のファイル権限管理はとにかく素晴らしいです。SUID、SGID、SBIT の機能を確...

JS の効率的なマジック演算子の概要

JavaScript は現在、毎年新しいバージョンがリリースされており、より便利で効率的な新しい演算...

Linux で g++ を使用してプログラムをコンパイルする際の -I (大文字の i)、-L (大文字の l)、-l (小文字の l) の機能の詳細な説明

初心者の Linux ユーザーとして、私は単純なgcc/g++操作を何度も使用してきましたが、少し複...

3Dカルーセル効果を実現するjs

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

Nginx 逆生成 Mogilefs 分散ストレージ例の詳細な説明

1. 分散ストレージシステムの概要情報技術の継続的な発展により、利便性がもたらされる一方で、データ量...

Ubuntu 20.04 aptの国内ソースを変更する方法

UPD 2020.2.26 現在、Ubuntu 20.04 LTSはまだリリースされていないため、チ...

JavaScript の Set データ構造の詳細な説明

目次1. セットとは何か2. セットコンストラクタ2.1) 配列2.2) 文字列2.3) 議論2.4...