React.cloneElement の使い方の詳しい説明

React.cloneElement の使い方の詳しい説明

いくつかのプロジェクトのメンテナンスを引き継ぐ必要があるため、チームのテクノロジー スタックは最近 Vue から React に切り替わりました。React 初心者として、またソース コードを通じて常に新しいことを学ぶのが好きなので、有名なプロジェクト antd のソース コードを読んで、React の使い方を学ぶことにしました。

ソースコードを読んでいると、多くのコンポーネントが React.cloneElement API を使用していることがわかりました。名前から何をするかは推測できましたが、具体的な機能はわかりませんでした。次に、公式ドキュメントを読みましたが、その機能は明確に説明されていましたが、どのようなシナリオで使用する必要があるのか​​はわかりませんでした。そこで、ドキュメントの説明に基づいて、ソースコードの使用と組み合わせ、Google と stackoverflow に焦点を当てて、いくつかの使用シナリオをまとめました。

cloneElementの役割

React.cloneElement() で、
 要素、
 [小道具],
 [...子供たち]
)

まず、この API の公式ドキュメントをご覧ください。

要素を開始点として使用して、新しい React 要素を複製して返します。結果の要素には、新しいプロパティが浅くマージされた元の要素のプロパティが含まれます。新しい子は既存の子を置き換えます。元の要素の key と ref は保持されます。

総括する:

  1. 元の要素を複製し、新しい React 要素を返します。
  2. 元の要素のプロパティを保持し、新しいプロパティを追加して、2 つを浅く結合します。
  3. key と ref もプロパティであるため保持され、変更することもできます。
  4. react のソースコードによれば、3 番目のパラメータから任意の数の子要素を定義できます。新しい子が定義されると、元の子は置き換えられます。

使用シナリオ

上記の定義に従って、さまざまなシナリオで必要に応じてこの API を使用できます。

新しい小道具を追加する

共通コンポーネントを作成するときに、内部ロジックに従って各子要素に異なるクラス名を追加する必要があります。このとき、 classNameを変更できます。

必要に応じて複数のTimelineItemを定義できる Timeline コンポーネントがあるとします。内部的には、最後の TimelineItem にtimeline-item-lastクラスを追加して、特殊効果をレンダリングしたいと考えています。現時点では、次の操作を実行できます。

定数MyTimeline = () => {
 戻る (
  <タイムライン>
   <タイムラインアイテム>2020-06-01</タイムラインアイテム>
   <タイムラインアイテム>2020-06-08</タイムラインアイテム>
   <タイムラインアイテム>2020-07-05</タイムラインアイテム>
  </タイムライン>
 )
}

// タイムライン内のロジックは次のようになります。import class from 'classnames';
const タイムライン = props => {
 // ...
 // ...
 React のプロパティを count 要素に追加します。
 const items = React.children.map(props.children, (item, index) => {
  React.cloneElement(item, { を返す
   クラス名: クラス([
    アイテム.props.className、
    'タイムライン項目'、
    インデックス === カウント - 1 ? 'タイムライン項目最後' : ''
   ])
  })
 }
 <div className={'timeline'}>{ items }</div> を返します。
}

classNameを追加するだけでなく、サブコンポーネントに props 情報を動的に追加することもできます。 react-routerSwitch 、一致するサブコンポーネントにlocationcomputedMatch情報を追加します。

クラスSwitchはReact.Componentを拡張します。
 与える() {
  戻る (
   <ルーターコンテキスト.コンシューマー>
    {コンテキスト => {
     invariant(context, "<Switch> を <Router> の外部で使用しないでください");

     const location = this.props.location || context.location;

     let 要素、一致;

     // React.Children.toArray().find() の代わりに React.Children.forEach を使用します
     // ここでtoArrayはすべての子要素にキーを追加するので、
     // 同じものをレンダリングする2つの <Route> のアンマウント/再マウントをトリガーします
     // 異なる URL にあるコンポーネント。
     React.Children.forEach(this.props.children, 子 => {
      マッチ == null && React.isValidElement(child) の場合 {
       要素 = 子;

       定数パス = child.props.path || child.props.from;

       一致 = パス
        ? matchPath(location.pathname, { ...child.props, path })
        : コンテキストに一致します。
      }
     });

     リターンマッチ
      React.cloneElement(要素、{場所、計算されたMatch:一致})
      : ヌル;
    }}
   </ルーターコンテキスト.コンシューマー>
  );
 }
}

プロップを変更するイベント

複数のTabPaneサブコンポーネントを含む Tab コンポーネントがあるとします。各TabPaneサブコンポーネントをクリックしたときに、Tab のonClickイベントをトリガーします。ユーザーは、各 TabPane に対して独立したonClickイベントを定義できます。この場合、サブコンポーネントのonClickイベントを変更する必要があります。

const Tab = props => {
 const { onClick } = プロパティ;
 const tabPanes = React.children.map(props.children, (tabPane, index) => {
  const ペインクリック = () => {
   onClick && onClick(インデックス);
   tabPane.props?.onClick();
  }
  React.cloneElement(tabPane, { を返します。
    onClick: ペインクリック、
  })
 })
 <div>{ tabPanes }</div> を返します。
}

カスタムスタイル

FollowMouseというコンポーネントを作成するときに、ユーザーがコンテンツ コンポーネントContentを定義できるようにします。マウスが移動すると、コンテンツのサイズに応じてContentの位置が自動的に計算され、画面からのオーバーフローを回避します。このとき、 cloneElementを使用してスタイルを動的に変更できます。

// 簡潔にするために、ここではマウス イベントは省略します。
const FollowMouse = props => {
 const { コンテンツ } = props;
 const customContent = React.isValidElement ? コンテンツ: <span>{ コンテンツ }</span>
 定数 getOffset = () => {
  戻る {
   位置: '絶対'、
   上: ...,
   左: ...、
  }
 }
 const renderContent = React.cloneElement(custonContent, {
  スタイル: {
   ...オフセット取得()
  }
 })
 <div>{renderContent() }</div> を返します。
}

キーを追加

要素のリストを作成するときに、 cloneElementを通じて各ノードにキーを追加できます。

const ComponentButton = props => {
 const { addonAfter, children } = props;
 const button = <button key='button'>{ children }</button>
 const list = [button, addonAfter ? React.cloneElement(addonAfter, { key: 'button-addon' } : null)
 <div>{リスト} <div> を返す
}

要約する

複雑なコンポーネントを開発する場合、必要に応じて子コンポーネントにさまざまな機能や表示効果を追加することがよくあります。React react自体は不変のオブジェクトです。 props.children実際にはchildrenではなく、単に子の記述childrenです。そのプロパティを変更することはできませんが、その内容を読み取ることはできます。したがって、 React.cloneElement使用すると、その要素をコピーし、新しい props を変更または追加して目的を達成できます。

もちろん、React の強力な組み合わせモードのおかげで、これはprops.childrenに限定されません。 props.leftprops.rightなど渡される他のpropsであっても、それが正当な react 要素である限り、このReact.cloneElementを使用して操作できます。

以上がReact.cloneElementの使い方の詳しい説明の内容です。React.cloneElementの使い方についてさらに詳しく知りたい方は、123WORDPRESS.COM内の他の関連記事もぜひご覧ください!

以下もご興味があるかもしれません:
  • React.Childrenの詳しい使い方
  • React Hooksの使用例
  • React Native の基本原則の深い理解 (Bridge of React Native)
  • React+Koa によるファイルアップロードの実装例
  • Reactフックとzarmコンポーネントライブラリ構成に基づいてh5フォームページを開発するためのサンプルコード
  • React antd タブの切り替えによりサブコンポーネントが繰り返し更新される
  • ReactJs 基礎チュートリアル - 基本編
  • ReactRouterの実装

<<:  MySQL 5.5.56 バージョン (バイナリ パッケージ インストール) カスタム インストール パス ステップ レコード

>>:  MySQL のバイナリおよび varbinary データ型の詳細な説明

推薦する

Vue3 コンパイルプロセス - ソースコード分析

序文: Vue3 がリリースされてからかなり経ちますが、最近、会社のプロジェクトでVue3 + Ty...

MySQL alter ignore構文の詳細な説明

今日仕事中に、ビジネス側から次のような質問をされました。テーブルがあり、一意のフィールドを追加する必...

Dockerは複数のポートマッピングコマンドを有効にします

次のように: docker run -d -p 5000:23 -p 5001:22 --name ...

CSS3 と JavaScript を使用して Web カラー ピッカーのサンプル コードを開発する

この例の Web カラー ピッカー機能は、ページ効果を実現するために CSS3 を使用します。つまり...

Ubuntu 18.04 Linux システムに JDK と Mysql をインストールする方法

プラットフォームの展開1. JDKをインストールするステップ1. OracleJDKをダウンロードす...

9999px に別れを告げる新しい CSS 画像置換テクニック (背景表示と画面外へのテキストの移動)

-9999 ピクセルの画像置換技術は、ここ 10 年近く人気があります。テキスト要素を画像に置き換え...

Linuxでスワップパーティションファイルを作成する方法

スワップの紹介Linux のスワップ (スワップ パーティション) は、Windows の仮想メモリ...

MySQL データベース操作 (作成、選択、削除)

MySQL データベースの作成MySQL サービスにログインしたら、create コマンドを使用し...

リクエスト IP の最後のセグメントに基づいてトラフィックを分割するように Nginx を構成する方法

これは主に、場所パラメータのif判断の設定ジャンプです。迂回により、サーバーの負荷と圧力を軽減できま...

DockerでVueプロジェクトをデプロイする方法を教えます

1.前面に書きます:軽量仮想化テクノロジーとして、Docker には継続的インテグレーション、バージ...

VMware 仮想マシンに CentOS と Qt をインストールするチュートリアル図

VMware のインストールパッケージのインストールダウンロードアドレス: https://www....

CSS最適化スキルの自己実践体験

1. CSS スプライトを使用します。利点は、CSS で使用される小さな画像を 1 つの大きな画像に...

複合主キーと複数列インデックスに遭遇した場合の MySQL 行ロックの詳細な説明

背景今日、他のプロジェクト チームと協力してシス​​テムのストレス テストを実施しているときに、プロ...

Windows で mysql5.7.21 をインストールするための詳細なチュートリアル

この記事では、参考までにMySQL 5.7.21のインストールチュートリアルを紹介します。具体的な内...

Mysql ルートユーザーアカウントのパスワードをリセットする問題を解決する

問題の説明: mysqladmin.exe を使用してコマンドを実行すると、次のエラー メッセージが...