著者は、 Creative Commons を選択して、 Write forDOnationsプログラムの一環として寄付を受け取りました。
序章
このチュートリアルでは、 React JavaScriptライブラリを使用して、小道具を使用してラッパーコンポーネントを作成します。 ラッパーコンポーネントは、不明なコンポーネントを囲むコンポーネントであり、子コンポーネントを表示するためのデフォルトの構造を提供します。 このパターンは、モーダル、テンプレートページ、情報タイルなど、デザイン全体で繰り返し使用されるユーザーインターフェイス(UI)要素を作成する場合に役立ちます。
ラッパーコンポーネントを作成するには、最初にRESTおよびSpread演算子を使用して未使用の小道具を収集し、ネストされたコンポーネントに渡す方法を学習します。 次に、組み込みを使用するコンポーネントを作成します children
ネストされたコンポーネントをJSXでHTML要素であるかのようにラップするコンポーネント。 最後に、コンポーネントを小道具として渡して、コンポーネント内の複数の場所にカスタムJSXを埋め込むことができる柔軟なラッパーを作成します。
チュートリアルでは、動物データのリストをカードの形式で表示するコンポーネントを作成します。 柔軟なラッピングコンポーネントを作成しながら、データを分割してコンポーネントをリファクタリングする方法を学びます。 このチュートリアルを終了すると、高度なプロップ技術を使用して、アプリケーションの成長と変化に応じて拡張および適応する再利用可能なコンポーネントを作成する、実用的なアプリケーションが完成します。
注:最初のステップでは、チュートリアル演習を作成するための空白のプロジェクトを設定します。 すでに作業中のプロジェクトがあり、小道具の操作に直接進みたい場合は、ステップ2から始めてください。
前提条件
-
Node.jsを実行する開発環境が必要になります。 このチュートリアルは、Node.jsバージョン10.20.1およびnpmバージョン6.14.4でテストされました。 これをmacOSまたはUbuntu18.04にインストールするには、Node.jsをインストールしてmacOSにローカル開発環境を作成する方法またはのPPAを使用したインストール]セクションの手順に従います。 Ubuntu18.04にNode.jsをインストールする方法。
-
このチュートリアルでは、 Create ReactAppを使用してアプリを作成します。 Create React Appを使用してアプリケーションをインストールする手順と、その動作に関する一般的な情報については、 CreateReactAppを使用してReactプロジェクトをセットアップする方法を参照してください。
-
Reactコンポーネントを使用します。これについては、Reactチュートリアルでカスタムコンポーネントを作成する方法で学ぶことができます。 また、小道具を使用してReactコンポーネントをカスタマイズする方法で学ぶことができる、React小道具の基本的な理解を深めるのにも役立ちます。
-
また、JavaScriptの基本的な知識も必要です。これは、 JavaScriptでコーディングする方法シリーズにあり、HTMLとCSSの基本的な知識もあります。 HTMLとCSSの優れたリソースは、 Mozilla DeveloperNetworkです。
ステップ1—空のプロジェクトを作成する
このステップでは、 Create ReactAppを使用して新しいプロジェクトを作成します。 次に、プロジェクトをブートストラップするときにインストールされるサンプルプロジェクトと関連ファイルを削除します。 最後に、コンポーネントを整理するための単純なファイル構造を作成します。 これにより、次のステップでこのチュートリアルのラッパーアプリケーションを構築するための確固たる基盤が得られます。
まず、新しいプロジェクトを作成します。 コマンドラインで次のスクリプトを実行し、を使用して新しいプロジェクトをインストールします。 create-react-app
:
- npx create-react-app wrapper-tutorial
プロジェクトが終了したら、次のディレクトリに移動します。
- cd wrapper-tutorial
新しいターミナルタブまたはウィンドウで、 CreateReactApp開始スクリプトを使用してプロジェクトを開始します。 ブラウザは変更時に自動更新されるため、作業中はこのスクリプトを実行したままにします。
- npm start
実行中のローカルサーバーを取得します。 プロジェクトがブラウザウィンドウで開かなかった場合は、 http:// localhost:3000/でプロジェクトを開くことができます。 これをリモートサーバーから実行している場合、アドレスは次のようになります。 http://your_domain:3000
.
ブラウザには、CreateReactAppの一部として含まれている単純なReactアプリケーションが読み込まれます。
完全に新しいカスタムコンポーネントのセットを構築するので、空のプロジェクトを作成できるように、ボイラープレートコードをクリアすることから始める必要があります。
開始するには、 src/App.js
テキストエディタで。 これは、ページに挿入されるルートコンポーネントです。 すべてのコンポーネントはここから始まります。 あなたはについてのより多くの情報を見つけることができます App.js
Create ReactAppを使用してReactプロジェクトを設定する方法。
開ける src/App.js
次のコマンドを使用します。
- nano 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
空のタグのセットを返すステートメント: <></>
. これにより、何も返さない有効なページが表示されます。 最終的なコードは次のようになります。
import React from 'react';
import './App.css';
function App() {
return <></>;
}
export default App;
テキストエディタを保存して終了します。
最後に、ロゴを削除します。 アプリケーションで使用することはないので、作業中に未使用のファイルを削除する必要があります。 長期的には混乱からあなたを救うでしょう。
ターミナルウィンドウで、次のコマンドを入力します。
- rm src/logo.svg
ブラウザを見ると、空白の画面が表示されます。
サンプルのCreateReactAppプロジェクトをクリアしたので、単純なファイル構造を作成します。 これにより、コンポーネントを分離して独立させることができます。
と呼ばれるディレクトリを作成します components
の中に src
ディレクトリ。 これにより、すべてのカスタムコンポーネントが保持されます。
- mkdir src/components
各コンポーネントには、スタイル、存在する場合は画像、およびテストとともにコンポーネントファイルを保存するための独自のディレクトリがあります。
のディレクトリを作成します App
:
- mkdir src/components/App
すべてを移動します App
そのディレクトリにファイル。 ワイルドカードを使用して、 *
、で始まるファイルを選択します App.
ファイル拡張子に関係なく。 次に、 mv
それらを新しいディレクトリに配置するコマンド:
- mv src/App.* src/components/App
次に、で相対インポートパスを更新します index.js
、これはプロセス全体をブートストラップするルートコンポーネントです。
- nano src/index.js
importステートメントは、 App.js
のファイル App
ディレクトリなので、次の強調表示された変更を行います。
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
ディレクトリ:
- nano 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
成分:
- mkdir src/components/AnimalCard
ディレクトで新しいファイルを開きます。
- nano src/components/AnimalCard/AnimalCard.js
次に、を取得するコンポーネントを追加します name
, diet
、 と size
小道具として表示します。
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
.
まず、コンポーネントを開きます。
- nano src/components/App/App.js
そこから、データをループして新しいデータを返すことができます AnimalCard
関連する小道具で。 強調表示された行をに追加します 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
とともに className
の wrapper
スタイリングを追加するために使用します。
このスタイリングを追加するには、 App.css
:
- nano src/components/App/App.css
ボイラープレートのスタイルを削除し、flexプロパティをというクラスに追加します wrapper
:
.wrapper {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
padding: 20px;
}
これは、フレックスボックスレイアウトを使用してデータを整理し、データが整列するようにします。 padding
ブラウザウィンドウにスペースを与え、 justify-content
要素間に余分なスペースを広げます。
ファイルを保存して終了します。 これを行うと、ブラウザが更新され、一部のデータが間隔を空けて表示されます。
詳細コンポーネントの作成
これで、データを表示する単純なコンポーネントができました。 しかし、あなたが与えたかったとしましょう diet
テキストを絵文字に変換して、データを少し洗練させます。 これを行うには、コンポーネントのデータを変換します。
Reactは柔軟に設計されているため、データを変換する方法を考えるときは、いくつかの異なるオプションがあります。
- コンポーネント内に、テキストを絵文字に変換する関数を作成できます。
- 関数を作成してコンポーネント外のファイルに保存すると、さまざまなコンポーネント間でロジックを再利用できます。
- テキストを絵文字に変換する別のコンポーネントを作成できます。
それぞれのアプローチは、適切なユースケースに適用すれば問題なく、アプリケーションを構築するときにそれらを切り替えることができます。 時期尚早の抽象化と複雑さを回避するには、最初のオプションを使用して開始する必要があります。 ロジックを再利用したい場合は、コンポーネントとは別に関数を引き出すことができます。 3番目のオプションは、ロジックとマークアップを含む再利用可能な部分が必要な場合、またはアプリケーション全体で使用するために分離したい場合に最適です。
この場合、後でデータを追加する必要があり、マークアップと変換ロジックを組み合わせているため、新しいコンポーネントを作成します。
新しいコンポーネントは呼び出されます AnimalDetails
. これを作成するには、新しいディレクトリを作成します。
- mkdir src/components/AnimalDetails
次に、開く AnimalDetails.js
テキストエディタで:
- nano src/components/AnimalDetails/AnimalDetails.js
ファイル内に、を表示する小さなコンポーネントを作成します diet
絵文字として:
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
:
- nano src/components/AnimalDetails/AnimalDetails.css
CSSを追加して、要素に境界線と余白を付け、コンポーネントの残りの部分から詳細を分離します。
.details {
border-top: gray solid 1px;
margin: 20px 0;
}
を使用しております .details
ルールを要素に一致させるには className
の details
.
ファイルを保存して閉じます。
新しいカスタムコンポーネントができたので、それを自分の AnimalCard
成分。 開ける AnimalCard.js
:
- nano src/components/AnimalCard/AnimalCard.js
交換してください diet.join
新しいステートメント AnimalDetails
コンポーネントとパス diet
ハイライトされた線を追加することにより、小道具として:
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
:
- nano src/components/AnimalCard/AnimalCard.js
内部で、削除します diet
分解されたオブジェクトから、代わりに小道具のrestをと呼ばれる変数に収集します props
. 次に、それらの小道具を直接に渡します AnimalDetails
:
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
オブジェクトは柔軟性を追加します。 scientificName
に AnimalDetails
経由 AnimalCard
成分。
まず、開く App.js
:
- nano src/components/App/App.js
次に、 scientificName
小道具として:
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
だからあなたは新しい小道具を消費することができます:
- nano src/components/AnimalDetails/AnimalDetails.js
新しい小道具は文字列になり、これをに追加します details
リストと宣言する行 PropType
:
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
. これは、新しいカードコンポーネントの標準スタイルを作成するためのラッパーコンポーネントになります。
新しいディレクトリを作成します。
- mkdir src/components/Card
次に、 Card
テキストエディタのコンポーネント:
- nano src/components/Card/Card.js
取るコンポーネントを作成します children
と title
小道具として、それらを div
次のコードを追加します。
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
:
- nano 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
:
- nano src/components/AnimalCard/AnimalCard.js
他の小道具とは異なり、あなたは合格しません children
明示的に。 代わりに、HTMLの子要素であるかのようにJSXを含めます。 つまり、次のように、要素内にネストするだけです。
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
成分:
- nano src/components/Card/Card.js
次に、という新しい小道具を追加します details
下に置きます <h2>
エレメント:
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
.
- nano src/components/AnimalCard/AnimalCard.js
以来 Card
コンポーネントはすでに使用しています children
、新しいJSXコンポーネントを小道具として渡す必要があります。 これらはすべて哺乳類なので、カードに追加しますが、包みます <em>
斜体にするためのタグ。
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である必要はありません。 たとえば、複雑なマークアップがある場合は、それを小道具に直接渡したくないでしょう。 これは読みにくいでしょう。 代わりに、別のコンポーネントを作成してから、そのコンポーネントを小道具として渡すことができます。
これが機能していることを確認するには、 AnimalDetails
に details
小道具:
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シリーズのコーディング方法ページに戻ってください。