開発者ドキュメント

小道具と反応してラッパーコンポーネントを作成する方法

著者は、 Creative Commons を選択して、 Write forDOnationsプログラムの一環として寄付を受け取りました。

序章

このチュートリアルでは、 React JavaScriptライブラリを使用して、小道具を使用してラッパーコンポーネントを作成します。 ラッパーコンポーネントは、不明なコンポーネントを囲むコンポーネントであり、子コンポーネントを表示するためのデフォルトの構造を提供します。 このパターンは、モーダル、テンプレートページ、情報タイルなど、デザイン全体で繰り返し使用されるユーザーインターフェイス(UI)要素を作成する場合に役立ちます。

ラッパーコンポーネントを作成するには、最初にRESTおよびSpread演算子を使用して未使用の小道具を収集し、ネストされたコンポーネントに渡す方法を学習します。 次に、組み込みを使用するコンポーネントを作成します children ネストされたコンポーネントをJSXHTML要素であるかのようにラップするコンポーネント。 最後に、コンポーネントを小道具として渡して、コンポーネント内の複数の場所にカスタムJSXを埋め込むことができる柔軟なラッパーを作成します。

チュートリアルでは、動物データのリストをカードの形式で表示するコンポーネントを作成します。 柔軟なラッピングコンポーネントを作成しながら、データを分割してコンポーネントをリファクタリングする方法を学びます。 このチュートリアルを終了すると、高度なプロップ技術を使用して、アプリケーションの成長と変化に応じて拡張および適応する再利用可能なコンポーネントを作成する、実用的なアプリケーションが完成します。

:最初のステップでは、チュートリアル演習を作成するための空白のプロジェクトを設定します。 すでに作業中のプロジェクトがあり、小道具の操作に直接進みたい場合は、ステップ2から始めてください。

前提条件

ステップ1—空のプロジェクトを作成する

このステップでは、 Create ReactAppを使用して新しいプロジェクトを作成します。 次に、プロジェクトをブートストラップするときにインストールされるサンプルプロジェクトと関連ファイルを削除します。 最後に、コンポーネントを整理するための単純なファイル構造を作成します。 これにより、次のステップでこのチュートリアルのラッパーアプリケーションを構築するための確固たる基盤が得られます。

まず、新しいプロジェクトを作成します。 コマンドラインで次のスクリプトを実行し、を使用して新しいプロジェクトをインストールします。 create-react-app:

  1. npx create-react-app wrapper-tutorial

プロジェクトが終了したら、次のディレクトリに移動します。

  1. cd wrapper-tutorial

新しいターミナルタブまたはウィンドウで、 CreateReactApp開始スクリプトを使用してプロジェクトを開始します。 ブラウザは変更時に自動更新されるため、作業中はこのスクリプトを実行したままにします。

  1. npm start

実行中のローカルサーバーを取得します。 プロジェクトがブラウザウィンドウで開かなかった場合は、 http:// localhost:3000/でプロジェクトを開くことができます。 これをリモートサーバーから実行している場合、アドレスは次のようになります。 http://your_domain:3000.

ブラウザには、CreateReactAppの一部として含まれている単純なReactアプリケーションが読み込まれます。

完全に新しいカスタムコンポーネントのセットを構築するので、空のプロジェクトを作成できるように、ボイラープレートコードをクリアすることから始める必要があります。

開始するには、 src/App.js テキストエディタで。 これは、ページに挿入されるルートコンポーネントです。 すべてのコンポーネントはここから始まります。 あなたはについてのより多くの情報を見つけることができます App.js Create ReactAppを使用してReactプロジェクトを設定する方法。

開ける src/App.js 次のコマンドを使用します。

  1. nano src/App.js

次のようなファイルが表示されます。

ラッパー-tutorial/src / App.js
import React from 'react';
import logo from './logo.svg';
import './App.css';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

行を削除します import logo from './logo.svg';. 次に、のすべてを置き換えます return 空のタグのセットを返すステートメント: <></>. これにより、何も返さない有効なページが表示されます。 最終的なコードは次のようになります。

ラッパー-tutorial/src / App.js

import React from 'react';
import './App.css';

function App() {
  return <></>;
}

export default App;

テキストエディタを保存して終了します。

最後に、ロゴを削除します。 アプリケーションで使用することはないので、作業中に未使用のファイルを削除する必要があります。 長期的には混乱からあなたを救うでしょう。

ターミナルウィンドウで、次のコマンドを入力します。

  1. rm src/logo.svg

ブラウザを見ると、空白の画面が表示されます。

サンプルのCreateReactAppプロジェクトをクリアしたので、単純なファイル構造を作成します。 これにより、コンポーネントを分離して独立させることができます。

と呼ばれるディレクトリを作成します components の中に src ディレクトリ。 これにより、すべてのカスタムコンポーネントが保持されます。

  1. mkdir src/components

各コンポーネントには、スタイル、存在する場合は画像、およびテストとともにコンポーネントファイルを保存するための独自のディレクトリがあります。

のディレクトリを作成します App:

  1. mkdir src/components/App

すべてを移動します App そのディレクトリにファイル。 ワイルドカードを使用して、 *、で始まるファイルを選択します App. ファイル拡張子に関係なく。 次に、 mv それらを新しいディレクトリに配置するコマンド:

  1. mv src/App.* src/components/App

次に、で相対インポートパスを更新します index.js、これはプロセス全体をブートストラップするルートコンポーネントです。

  1. nano src/index.js

importステートメントは、 App.js のファイル App ディレクトリなので、次の強調表示された変更を行います。

ラッパー-tutorial/src / index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './components/App/App';
import * as serviceWorker from './serviceWorker';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();

ファイルを保存して終了します。

プロジェクトが設定されたので、最初のコンポーネントを作成できます。

ステップ2—未使用の小道具を収集する ...props

このステップでは、動物のグループに関するデータのセットを表示するコンポーネントを作成します。 コンポーネントには、情報を視覚的に表示するための2番目のネストされたコンポーネントが含まれます。 親とネストされたコンポーネントを接続するには、RESTおよびSpread演算子を使用して、親が小道具の名前や種類を意識することなく、未使用の小道具を親から子に渡します。

このステップの終わりまでに、小道具が何であるかを知らなくても、ネストされたコンポーネントに小道具を提供できる親コンポーネントができあがります。 これにより、親コンポーネントが柔軟に保たれ、親を変更せずに子コンポーネントを更新できるようになります。

の作成 AnimalCard 成分

まず、動物のデータセットを作成します。 まず、データセットを含むファイルを開きます。 components/App ディレクトリ:

  1. nano src/components/App/data.js

次のデータを追加します。

src / components / App / data.js

export default [
  {
    name: 'Lion',
    scientificName: 'Panthero leo',
    size: 140,
    diet: ['meat']
  },
  {
    name: 'Gorilla',
    scientificName: 'Gorilla beringei',
    size: 205,
    diet: ['plants', 'insects']
  },
  {
    name: 'Zebra',
    scientificName: 'Equus quagga',
    size: 322,
    diet: ['plants'],
  }
]

この動物のリストは、オブジェクト配列であり、動物の名前、学名、体重、および食事が含まれています。

ファイルを保存して閉じます。

次に、のディレクトリを作成します AnimalCard 成分:

  1. mkdir src/components/AnimalCard

ディレクトで新しいファイルを開きます。

  1. nano src/components/AnimalCard/AnimalCard.js

次に、を取得するコンポーネントを追加します name, diet、 と size 小道具として表示します。

ラッパー-tutorial/src / components / AnimalCard / AnimalCard.js
import React from 'react';
import PropTypes from 'prop-types';

export default function AnimalCard({ diet, name, size }) {
  return(
    <div>
      <h3>{name}</h3>
      <div>{size}kg</div>
      <div>{diet.join(', ')}.</div>
    </div>
  )
}

AnimalCard.propTypes = {
  diet: PropTypes.arrayOf(PropTypes.string).isRequired,
  name: PropTypes.string.isRequired,
  size: PropTypes.number.isRequired,
}

これが破壊のパラメータリストの小道具です。 AnimalCard 関数、次にデータを表示します div. The diet データは、 join()メソッドを使用して単一の文字列としてリストされます。 各データには、データ型が正しいことを確認するために、対応するPropTypeが含まれています。

ファイルを保存して閉じます。

コンポーネントとデータが揃ったので、それらを組み合わせる必要があります。 これを行うには、コンポーネントとデータをプロジェクトのルートコンポーネントにインポートします。 App.js.

まず、コンポーネントを開きます。

  1. nano src/components/App/App.js

そこから、データをループして新しいデータを返すことができます AnimalCard 関連する小道具で。 強調表示された行をに追加します App.js:

ラッパー-tutorial/src / components / App / App.js
import React from 'react';
import './App.css';

import animals from './data';
import AnimalCard from '../AnimalCard/AnimalCard';

function App() {
  return (
    <div className="wrapper">
      {animals.map(animal =>
        <AnimalCard
          diet={animal.diet}
          key={animal.name}
          name={animal.name}
          size={animal.size}
        />
      )}
    </div>
  );
}

export default App;

ファイルを保存して閉じます。

より複雑なプロジェクトで作業する場合、データは API localStorage 、静的ファイルなど、より多様な場所から取得されます。 ただし、これらのそれぞれを使用するプロセスは似ています。データを変数に割り当て、データをループします。 この場合、データは静的ファイルからのものであるため、変数に直接インポートしています。

このコードでは、 .map()メソッドを使用して繰り返し処理します animals 小道具を表示します。 すべてのデータを使用する必要はないことに注意してください。 明示的に渡していない scientificName たとえば、プロパティ。 また、別のものを追加しています key Reactがマップされたデータを追跡するために使用する小道具。 最後に、コードを div とともに classNamewrapper スタイリングを追加するために使用します。

このスタイリングを追加するには、 App.css:

  1. nano src/components/App/App.css

ボイラープレートのスタイルを削除し、flexプロパティをというクラスに追加します wrapper:

prop-tutorial / src / components / App / App.css
.wrapper {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    padding: 20px;
}

これは、フレックスボックスレイアウトを使用してデータを整理し、データが整列するようにします。 padding ブラウザウィンドウにスペースを与え、 justify-content 要素間に余分なスペースを広げます。

ファイルを保存して終了します。 これを行うと、ブラウザが更新され、一部のデータが間隔を空けて表示されます。

詳細コンポーネントの作成

これで、データを表示する単純なコンポーネントができました。 しかし、あなたが与えたかったとしましょう diet テキストを絵文字に変換して、データを少し洗練させます。 これを行うには、コンポーネントのデータを変換します。

Reactは柔軟に設計されているため、データを変換する方法を考えるときは、いくつかの異なるオプションがあります。

それぞれのアプローチは、適切なユースケースに適用すれば問題なく、アプリケーションを構築するときにそれらを切り替えることができます。 時期尚早の抽象化と複雑さを回避するには、最初のオプションを使用して開始する必要があります。 ロジックを再利用したい場合は、コンポーネントとは別に関数を引き出すことができます。 3番目のオプションは、ロジックとマークアップを含む再利用可能な部分が必要な場合、またはアプリケーション全体で使用するために分離したい場合に最適です。

この場合、後でデータを追加する必要があり、マークアップと変換ロジックを組み合わせているため、新しいコンポーネントを作成します。

新しいコンポーネントは呼び出されます AnimalDetails. これを作成するには、新しいディレクトリを作成します。

  1. mkdir src/components/AnimalDetails

次に、開く AnimalDetails.js テキストエディタで:

  1. nano src/components/AnimalDetails/AnimalDetails.js

ファイル内に、を表示する小さなコンポーネントを作成します diet 絵文字として:

ラッパー-チュートリアル/src/components/AnimalDetails/AnimalDetails.js
import React from 'react';
import PropTypes from 'prop-types';
import './AnimalDetails.css';

function convertFood(food) {
  switch(food) {
    case 'insects':
      return '🐜';
    case 'meat':
      return '🍖';
    case 'plants':
    default:
      return '🌱';
  }
}

export default function AnimalDetails({ diet }) {
  return(
    <div className="details">
      <h4>Details:</h4>
      <div>
        Diet: {diet.map(food => convertFood(food)).join(' ')}
      </div>
    </div>
  )
}

AnimalDetails.propTypes = {
  diet: PropTypes.arrayOf(PropTypes.string).isRequired,
}

The AnimalDetails.propTypes オブジェクトは、の小道具を取る関数を設定します diet それは文字列の配列です。 次に、コンポーネント内で、コードがループします。 diet switchステートメントを使用して文字列を絵文字に変換します。

ファイルを保存して閉じます。

CSSもインポートしているので、ここで追加しましょう。

開ける AnimalDetails.css:

  1. nano src/components/AnimalDetails/AnimalDetails.css

CSSを追加して、要素に境界線と余白を付け、コンポーネントの残りの部分から詳細を分離します。

ラッパー-チュートリアル/src/components/AnimalDetails/AnimalDetails.css
.details {
    border-top: gray solid 1px;
    margin: 20px 0;
}

を使用しております .details ルールを要素に一致させるには classNamedetails.

ファイルを保存して閉じます。

新しいカスタムコンポーネントができたので、それを自分の AnimalCard 成分。 開ける AnimalCard.js:

  1. nano src/components/AnimalCard/AnimalCard.js

交換してください diet.join 新しいステートメント AnimalDetails コンポーネントとパス diet ハイライトされた線を追加することにより、小道具として:

ラッパー-tutorial/src / components / AnimalCard / AnimalCard.js
import React from 'react';
import PropTypes from 'prop-types';
import AnimalDetails from '../AnimalDetails/AnimalDetails';

export default function AnimalCard({ diet, name, size }) {
  return(
    <div>
      <h3>{name}</h3>
      <div>{size}kg</div>
      <AnimalDetails
        diet={diet}
      />
    </div>
  )
}

AnimalCard.propTypes = {
  diet: PropTypes.arrayOf(PropTypes.string).isRequired,
  name: PropTypes.string.isRequired,
  size: PropTypes.number.isRequired,
}

ファイルを保存すると、ブラウザに新しい詳細が表示されます。

コンポーネントを介して詳細を渡す ...props

コンポーネントは一緒にうまく機能していますが、わずかな非効率性があります AnimalCard. あなたは明示的に引っ張っています diet から props 引数ですが、データを使用していません。 代わりに、それをコンポーネントに渡します。 これについて本質的に悪いことは何もありません。実際、コミュニケーションが多すぎるという側面で誤りを犯したほうがよい場合がよくあります。 ただし、これを行うと、コードの保守がより困難になります。 新しいデータをに渡したいときはいつでも AnimalDetails、3つの場所を更新する必要があります。 App、小道具を渡すところ、 AnimalDetails、小道具を消費し、 AnimalCard、これは仲介者です。

より良い方法は、未使用の小道具を中に集めることです AnimalCard そしてそれらを直接に渡します AnimalDetails. これにより、変更を加えることができます AnimalDetails 変更せずに AnimalCard. 事実上、 AnimalCard 小道具や PropTypes 入っている AnimalDetails.

これを行うには、オブジェクトレスト演算子を使用します。 このオペレーターは、分解中に引き出されなかったアイテムを収集し、それらを新しいオブジェクトに保存します。

簡単な例を次に示します。

const dog = {
    name: 'dog',
    diet: ['meat']
}

const { name, ...props  } = dog;

この場合、変数 name になります 'dog' と変数 props になります { diet: ['meat']}.

これまで、すべての小道具をHTML属性であるかのように渡してきましたが、オブジェクトを使用して小道具を送信することもできます。 オブジェクトを小道具として使用するには、スプレッド演算子を使用する必要があります—...props—中括弧で囲まれています。 これにより、各キーと値のペアが小道具に変更されます。

開ける AnimalCard.js:

  1. nano src/components/AnimalCard/AnimalCard.js

内部で、削除します diet 分解されたオブジェクトから、代わりに小道具のrestをと呼ばれる変数に収集します props. 次に、それらの小道具を直接に渡します AnimalDetails:

ラッパー-tutorial/src / components / AnimalCard / AnimalCard.js
import React from 'react';
import PropTypes from 'prop-types';
import AnimalDetails from '../AnimalDetails/AnimalDetails';

export default function AnimalCard({ name, size, ...props }) {
  return(
    <div>
      <h3>{name}</h3>
      <div>{size}kg</div>
      <AnimalDetails
        {...props}
      />
    </div>
  )
}

AnimalCard.propTypes = {
  name: PropTypes.string.isRequired,
  size: PropTypes.number.isRequired,
}

を削除できることに注意してください diet PropType このコンポーネントでは小道具を使用していないためです。

この場合、あなたは1つの小道具だけをに渡します AnimalDetails. 複数の小道具がある場合は、順序が重要になります。 後の小道具は前の小道具を上書きするので、優先したい小道具がある場合は、それが最後であることを確認してください。 これにより、混乱が生じる可能性があります。 props オブジェクトには、名前付きの値でもあるプロパティがあります。

ファイルを保存して閉じます。 ブラウザが更新され、すべてが同じように見えます。

どのように ...props オブジェクトは柔軟性を追加します。 scientificNameAnimalDetails 経由 AnimalCard 成分。

まず、開く App.js:

  1. nano src/components/App/App.js

次に、 scientificName 小道具として:

ラッパー-tutorial/src / components / App / App.js
import React from 'react';
import './App.css';

import animals from './data';
import AnimalCard from '../AnimalCard/AnimalCard';

function App() {
  return (
    <div className="wrapper">
      {animals.map(animal =>
        <AnimalCard
          diet={animal.diet}
          key={animal.name}
          name={animal.name}
          size={animal.size}
          scientificName={animal.scientificName}
        />
      )}
    </div>
  );
}

export default App;

ファイルを保存して閉じます。

飛ばす AnimalCard; そこで変更を加える必要はありません。 次に開きます AnimalDetails だからあなたは新しい小道具を消費することができます:

  1. nano src/components/AnimalDetails/AnimalDetails.js

新しい小道具は文字列になり、これをに追加します details リストと宣言する行 PropType:

ラッパー-チュートリアル/src/components/AnimalDetails/AnimalDetails.js
import React from 'react';
...
export default function AnimalDetails({ diet, scientificName }) {
  return(
    <div className="details">
      <h4>Details:</h4>
      <div>
        Scientific Name: {scientificName}.
      </div>
      <div>
        Diet: {diet.map(food => convertFood(food)).join(' ')}
      </div>
    </div>
  )
}

AnimalDetails.propTypes = {
  diet: PropTypes.arrayOf(PropTypes.string).isRequired,
  scientificName: PropTypes.string.isRequired,
}

ファイルを保存して閉じます。 これを行うと、ブラウザが更新され、変更なしで新しい詳細が表示されます。 AnimalCard 成分:

このステップでは、未知の小道具を受け取り、spread演算子を使用してネストされたコンポーネントに渡すことができる柔軟な親小道具を作成する方法を学びました。 これは、焦点を絞った責任を持つコンポーネントを作成するために必要な柔軟性を提供する一般的なパターンです。 次のステップでは、組み込みのを使用して、未知のコンポーネントを小道具として使用できるコンポーネントを作成します。 children 小道具。

ステップ3—を使用してラッパーコンポーネントを作成する children

このステップでは、未知のコンポーネントのグループを小道具として受け取ることができるラッパーコンポーネントを作成します。 これにより、標準のHTMLのようなコンポーネントをネストできるようになり、再利用可能なラッパーを作成するためのパターンが得られます。これにより、共通のデザインでありながら柔軟なインテリアを必要とするさまざまなコンポーネントを作成できます。

Reactはあなたに呼ばれる組み込みの小道具を与えます children 子コンポーネントを収集します。 これを使用すると、ラッパーコンポーネントの作成が直感的で読みやすくなります。

まず、という新しいコンポーネントを作成します Card. これは、新しいカードコンポーネントの標準スタイルを作成するためのラッパーコンポーネントになります。

新しいディレクトリを作成します。

  1. mkdir src/components/Card

次に、 Card テキストエディタのコンポーネント:

  1. nano src/components/Card/Card.js

取るコンポーネントを作成します childrentitle 小道具として、それらを div 次のコードを追加します。

ラッパー-tutorial/src / components / Card / Card.js
import React from 'react';
import PropTypes from 'prop-types';
import './Card.css';

export default function Card({ children, title }) {
  return(
    <div className="card">
      <div className="card-details">
        <h2>{title}</h2>
      </div>
      {children}
    </div>
  )
}

Card.propTypes = {
  children: PropTypes.oneOfType([
    PropTypes.arrayOf(PropTypes.element), 
    PropTypes.element.isRequired
  ]),
  title: PropTypes.string.isRequired,
}

The PropTypes のために children 新しいです。 The children propは、JSX要素またはJSX要素の配列のいずれかです。 The title 文字列です。

ファイルを保存して閉じます。

次に、スタイリングを追加します。 開ける Card.css:

  1. nano src/components/Card/Card.css

カードの詳細の下に境界線と線が表示されます。

ラッパー-tutorial/src / components / Card / Card.css
.card {
    border: black solid 1px;
    margin: 10px;
    padding: 10px;
    width: 200px;
}

.card-details {
    border-bottom: gray solid 1px;
    margin-bottom: 20px;
}

ファイルを保存して閉じます。 コンポーネントができたので、それを使用する必要があります。 あなたはそれぞれを包むことができます AnimalCard とともに Card のコンポーネント App.js、しかし名前以来 AnimalCard すでに Card、を使用する方が良いでしょう Card 内部のコンポーネント AnimalCard.

開く AnimalCard:

  1. nano src/components/AnimalCard/AnimalCard.js

他の小道具とは異なり、あなたは合格しません children 明示的に。 代わりに、HTMLの子要素であるかのようにJSXを含めます。 つまり、次のように、要素内にネストするだけです。

ラッパー-tutorial/src / components / AnimalCard / AnimalCard.js
import React from 'react';
import PropTypes from 'prop-types';
import Card from '../Card/Card';
import AnimalDetails from '../AnimalDetails/AnimalDetails';

export default function AnimalCard({ name, size, ...props }) {
  return(
    <Card title="Animal">
      <h3>{name}</h3>
      <div>{size}kg</div>
      <AnimalDetails
        {...props}
      />
    </Card>
  )
}

AnimalCard.propTypes = {
  name: PropTypes.string.isRequired,
  size: PropTypes.number.isRequired,
}

Reactコンポーネントとは異なり、子として単一のルート要素を持つ必要はありません。 だからこそ PropType 為に Card 要素の配列または単一の要素である可能性があることを指定しました。 合格に加えて children ネストされたコンポーネントとして、カードに次のタイトルを付けます Animal.

ファイルを保存して閉じます。 これを行うと、ブラウザが更新され、更新されたカードコンポーネントが表示されます。

今、あなたは再利用可能です Card ネストされた子をいくつでも取ることができるコンポーネント。 これの主な利点は、再利用できることです Card 任意のコンポーネントで。 あなたが作りたいなら Plant カード、あなたは植物情報をで包むことによってそれをすることができます Card 成分。 それはまったく関係する必要さえありません:あなたが再利用したいなら Card 音楽やアカウントデータなどを一覧表示するまったく異なるアプリケーションのコンポーネントでも、それを行うことができます。 The Card コンポーネントは子が何であるかを気にしません。 ラッパー要素を再利用しているだけです。この場合は、スタイル付きの境界線とタイトルです。

使用することの欠点 children 子プロップのインスタンスは1つしか持てないということです。 場合によっては、コンポーネントにカスタムJSXを複数の場所に配置する必要があります。 幸い、JSXコンポーネントとReactコンポーネントを小道具として渡すことでこれを行うことができます。これについては、次のステップで説明します。

ステップ4—コンポーネントを小道具として渡す

このステップでは、 Card 他のコンポーネントを小道具として使用するコンポーネント。 これにより、コンポーネントは、ページ全体の複数の場所に不明なコンポーネントまたはJSXを表示するための最大限の柔軟性が得られます。 ようではない children、一度しか使用できませんが、小道具と同じ数のコンポーネントを使用できるため、ラッパーコンポーネントは、標準の外観と構造を維持しながら、さまざまなニーズに適応できます。

この手順を完了すると、子コンポーネントをラップしたり、カード内の他のコンポーネントを表示したりできるコンポーネントができあがります。 このパターンは、単純な文字列や整数よりも複雑な情報を必要とするコンポーネントを作成する必要がある場合に柔軟性を提供します。

変更してみましょう Card と呼ばれる任意のReact要素を取るコンポーネント details.

まず、 Card 成分:

  1. nano src/components/Card/Card.js

次に、という新しい小道具を追加します details 下に置きます <h2> エレメント:

ラッパー-tutorial/src / components / Card / Card.js
import React from 'react';
import PropTypes from 'prop-types';
import './Card.css';

export default function Card({ children, details, title }) {
  return(
    <div className="card">
      <div className="card-details">
        <h2>{title}</h2>
        {details}
      </div>
      {children}
    </div>
  )
}

Card.propTypes = {
  children: PropTypes.oneOfType([
    PropTypes.arrayOf(PropTypes.element), 
    PropTypes.element.isRequired
  ]),
  details: PropTypes.element,
  title: PropTypes.string.isRequired,
}

Card.defaultProps = {
  details: null,
}

この小道具はと同じタイプになります children、ただし、オプションである必要があります。 オプションにするには、デフォルト値を追加します。 null. この場合、ユーザーが詳細を渡さなくても、コンポーネントは引き続き有効であり、余分なものは何も表示されません。

ファイルを保存して閉じます。 ページが更新され、以前と同じ画像が表示されます。

次に、いくつかの詳細を追加します AnimalCard. まず、開く AnimalCard.

  1. nano src/components/AnimalCard/AnimalCard.js

以来 Card コンポーネントはすでに使用しています children、新しいJSXコンポーネントを小道具として渡す必要があります。 これらはすべて哺乳類なので、カードに追加しますが、包みます <em> 斜体にするためのタグ。

ラッパー-tutorial/src / components / AnimalCard / AnimalCard.js
import React from 'react';
...

export default function AnimalCard({ name, size, ...props }) {
  return(
    <Card title="Animal" details={<em>Mammal</em>}>
      <h3>{name}</h3>
      <div>{size}kg</div>
      <AnimalDetails
        {...props}
      />
    </Card>
  )
}
...

ファイルを保存します。 これを行うと、ブラウザが更新され、Mammalというフレーズを含む更新が表示されます。

この小道具は、あらゆるサイズのJSXを使用できるため、すでに強力です。 この例では、要素を1つだけ追加しましたが、必要なだけJSXを渡すことができます。 また、JSXである必要はありません。 たとえば、複雑なマークアップがある場合は、それを小道具に直接渡したくないでしょう。 これは読みにくいでしょう。 代わりに、別のコンポーネントを作成してから、そのコンポーネントを小道具として渡すことができます。

これが機能していることを確認するには、 AnimalDetailsdetails 小道具:

ラッパー-tutorial/src / components / AnimalCard / AnimalCard.js
import React from 'react';
...

export default function AnimalCard({ name, size, ...props }) {
  return(
    <Card
      title="Animal"
      details={
        <AnimalDetails
          {...props}
        />
      }
    >
      <h3>{name}</h3>
      <div>{size}kg</div>
    </Card>
  )
}
...

AnimalDetails より複雑で、マークアップの行がいくつかあります。 直接追加する場合 details、それは小道具を大幅に増やし、読みにくくします。

ファイルを保存して閉じます。 これを行うと、ブラウザが更新され、カードの上部に詳細が表示されます。

今、あなたは Card カスタムJSXを取得して、複数の場所に配置できるコンポーネント。 あなたは単一の小道具に制限されていません。 必要な数の小道具に要素を渡すことができます。 これにより、柔軟なラッピングコンポーネントを作成して、他の開発者が全体的なスタイルと機能を維持しながらコンポーネントをカスタマイズできるようになります。

コンポーネントを小道具として渡すことは完璧ではありません。 読むのが少し難しく、合格するほど明確ではありません children、ただし、これらは同じように柔軟性があり、コンポーネントで必要な数だけ使用できます。 あなたは使用する必要があります children 最初に、しかしそれが十分でない場合は小道具にフォールバックすることを躊躇しないでください。

このステップでは、JSXコンポーネントとReactコンポーネントを小道具として別のコンポーネントに渡す方法を学びました。 これにより、ラッパーコンポーネントがJSXまたはコンポーネントを処理するために複数の小道具を必要とする可能性がある多くの状況を処理する柔軟性がコンポーネントに与えられます。

結論

予測可能な外観と構造を維持しながら、データを柔軟に表示できるさまざまなラッピングコンポーネントを作成しました。 未知の小道具を収集してネストされたコンポーネントに渡すことができるコンポーネントを作成しました。 ビルトインも使用しました children 任意の数のネストされた要素を処理できるラッパーコンポーネントを作成するためのprop。 最後に、JSXまたはReactコンポーネントを小道具として使用できるコンポーネントを作成し、ラッパーコンポーネントがさまざまなカスタマイズの複数のインスタンスを処理できるようにしました。

ラッパーコンポーネントを使用すると、コードの再利用と一貫性を最大化しながら、未知の状況に適応することができます。 このパターンは、ボタン、アラート、モーダル、スライドショーなど、アプリケーション全体で再利用する基本的なUI要素を作成するのに役立ちます。 あなたは何度もそれに戻っていることに気付くでしょう。

Reactのチュートリアルをもっと見たい場合は、 Reactトピックページを確認するか、React.jsシリーズのコーディング方法ページに戻ってください。

モバイルバージョンを終了