オブジェクトを含む配列があります。 span
コンポーネントを使用して名前をレンダリングするために、この配列のマップを作成しています。
let data = [{"id": "01", "name": "Hi"}, {"id": "02", "name": "Hello"}];
私は、以下の2つの異なる機能を使用してオブジェクトの配列を反復処理し、mapを使用してJSX要素をレンダリングしています。
import React, { Component } from 'react';
class App extends Component {
render() {
let data = [{"id": "01", "name": "Hi"}, {"id": "02", "name": "Hello"}];
const items = data.map((key, i) => {
return <span key={key.id}>{key.name}</span>;
});
return (
<div>
{items}
</div>
);
}
}
export default App;
import React, { Component } from 'react';
class App extends Component {
render() {
let data = [{"id": "01", "name": "Hi"}, {"id": "02", "name": "Hello"}];
let rows = [];
data.map((key, i) => {
rows.Push(<span key={key.id}>{key.name}</span>);
});
return (
<div>
{rows}
</div>
);
}
}
export default App;
map
を使用してJSX要素をレンダリングする上記の2つの異なる方法を知っていました。これら2つ以外に、同じことを行う他の方法はありますか?もしそうなら、どちらが推奨されますか?
ほとんどの場合、私はこのルールに従います。
アイテムをレンダリングするコンポーネントを作成します
// in some file
export const RenderItems = ({data}) => {
return data && data.map((d, i) => <span key={d.id}>{d.name}</span>) || null
}
RenderItemsをフックします
import { RenderItems } from 'some-file'
class App extends Component {
render() {
// you may also define data here instead of getting data from props
const { data } = this.props
return (
<div>
<RenderItems data={data} />
</div>
)
}
}
コンポーネントにデータを添付します
const data = [{"id": "01", "name": "Hi"}, {"id": "02", "name": "Hello"}]
<App data={data} />
このルールに従うことは、コードの2番目の例でもパフォーマンスに影響を与えません。配列内のアイテムをプッシュし、アイテムをレンダリングします。なぜなら、レンダーフック内で直接作業しているわけではないからです。レンダーフックがその内部にロジックを直接実装しないように常に注意してください。
さらに、キーを使用するためだけにid
を作成することはありません。
const data = [{"name": "Hi"}, {"name": "Hello"}]
//... and when using index as key
.map((d, i) => <span key={'item-'+i}>
// or,
.map((d, i) => <span key={'item-'+i+'-'+d.name}>
この投稿 インデックスをキーとして使用しながらこの構文に従う理由を参照してください。
不要なhtmlタグが使用されないようにしたい場合は、 React.Fragment を使用できます。
export const RenderItems = ({data}) => {
return data &&
data.map(
(d, i) => <React.Fragment key={d.id}>{d.name}</React.Fragment>
) || null
}
// and when rendering, you just return the component
return <RenderItems data={data} />
注:
<></>
を<React.Fragment></React.Fragment>
のエイリアスとして使用できます。キープロパティを使用しているので、使用していません。React.Fragment
の短い表記をサポートしてください。<></>
の使用例:
<>{d.name}</>
これは、タグなしでhtmlでd.name
の値にレンダリングされます。これは、既存の設計をアプリケーションに対応するように特別に変換する場合に最適と見なされます。または、他の場合もあります。同様に、定義リストを表示します。
<dl>
<dt></dt>
<dd></dd>
<dt></dt>
<dd></dd>
<dt></dd>
</dl>
また、不要なhtmlタグを付けたくない場合は、Fragmentを使用すると作業が楽になります。
例:
<>
<dt>{d.term}</dt>
<dd>{d.definition}</dd>
</>
最も重要なケースは、td
(TRコンポーネント)のtr
要素をレンダリングする場合です。そうでない場合は、HTMLのルールに違反しています。コンポーネントは正しくレンダリングされません。反応すると、エラーがスローされます。
また、 小道具の長いリスト 以下のようになっている場合:
const {
items,
id,
imdbID,
title,
poster,
getMovieInfo,
addToFavorites,
isOpen,
toggleModal,
closeModal,
modalData,
} = props
あなたは次のように破壊することを検討するかもしれません:
const { items, ...other } = props
// and in your component you can use like:
<div modalData={other.modalData}>
しかし、個人的には最初のサンプルコードを使用することを好みます。これは、開発中に他のコンポーネントを振り返ったり、コンソールを毎回探す必要がないためです。与えられた例では、modalData={}
のようなキーがあるので、modalData={other.modalData}
を簡単に維持できます。しかし、<div>{modalData}</div>
のようにコーディングする必要がある場合はどうでしょうか。次に、あなたも私の好みに同意するかもしれません。
私はこれをします
const data = [{id: 1, name: 'a'}, {id: 2, name: 'b'}];
export default class App extends PureComponent {
render() {
return (
<div>
{data.map(({ id, name }) => <span key={id}>{name}</span>)}
</div>
);
}
}
これで、data
がすべてのレンダリングで再インスタンス化されるわけではなく、不要な変数宣言をガベージコレクションする必要がありません。
最初の方法の方が優れています。
Array.prototype.map
は舞台裏で配列を作成し、各要素に変更を適用した後にそれを返します。 Functionality-1は2つの配列を作成し、Functionality-2は3つの配列を作成します。
Functionality-1の方が読みやすくなっています。 Reactコードは通常書かれています。このような単純な要素の場合、const定義を保存します。アイテムを作成し、mapステートメントを[〜#〜] jsx [〜#〜]に入れて、直接返されます。
一般に、for
またはwhile
ステートメントは、配列を反復する最も効率的な方法です。重要でない場所で小さなアレイを処理する方法は、マイクロ最適化と見なすことができます。
map
の使用は、Reactコンポーネントでは慣用的です。これは、十分に高速で、式の一部として値を返すことができるためです。
これはアンチパターンですが、次のようになります。
let rows = [];
data.map((key, i) => {
rows.Push(<span key={key.id}>{key.name}</span>);
});
map
は、forEach
または他のループの代わりに配列を反復するのではなく、配列要素を他の値(したがって名前)にマップすることになっています。この問題はESLintで追跡できます array-callback-return
ルール。
コンポーネントはステートレスであり、Component
クラスである必要はありません。機能コンポーネントまたはPureComponent
クラスにすることができます。 data
は定数であるため、レンダリングごとに割り当てる必要はありません。
const data = [{"id": "01", "name": "Hi"}, {"id": "02", "name": "Hello"}];
const App = props => <div>
{data.map(({ id, name }) => <span key={id}>{name}</span>)}
</div>;
最初の方法は正しいです。 map関数を使用して、配列を反復処理します。
export default class App extends React.Component{
constructor(props){
super(props);
this.state = {
data: [{"id": "01", "name": "Hi"}, {"id": "02", "name": "Hello"}];
};
}
render(){
return(
<div>
{this.state.data.map((data,index)=>
<span key={data.id}>{data.name}</span>
)}
);
}
}
Mapが配列を返すので、return(...)
内のmap
を使用します。それは私が個人的に努力しているもので、よりクリーンで読みやすいものです。
答えに追加するために、配列data
がレーンを下って変更される可能性がある場合は、新しいステートレスダンプコンポーネントを作成します。
const Spanner = props => { return <span key={ props.data.id }>{ props.data.name }</span> };
class App extends Component {
render() {
let data = [{"id": "01", "name": "Hi"}, {"id": "02", "name": "Hello"}];
return (
<div>
{
data.map( (item, ind) => {
return (<Spanner key={item.id} data={item.name} />);
})
}
</div>
);
}
}
}
このようにして、このSpannerコンポーネントを、異なるコンポーネント間で共有される共通コンポーネントとして使用できます。また、data
が時間の経過とともに変化する場合(ほとんどの場合、変化します)、ラッパー関数をSpannerコンポーネントに記述し、必要に応じて新しい関数を呼び出すことができます。 data=[{"id": "01", "name": "Hi", "userType": "Admin"}, {"id": "02", "name": "Hello", "userType": "Client"}];
const UserWidget = (props) => {
return (
<div>
<h4>{ props.type }</h4>
<Spanner key={ props.key } data={ props.name }/>
</div>
);
}
// now both the UserWidget and the Spanner Components can be used wherever required
// say a dashboard Component wants to use the UserWidget
class Dashboard extends Component {
render() {
let data = [{"id": "01", "name": "Hi", "userType": "Admin"}, {"id": "02", "name": "Hello", "userType": "Client"}];
return (
<div>
{
data.map( (item, ind) => {
return (<UserWidget type={ item.userType } key={item.id} data={item.name} />);
})
}
</div>
);
}
}
}
このようにして、自分自身を繰り返すことはなく、新しいdata
配列に新しいキーuserType
が含まれていても、AppComponentは期待どおりの動作を維持します。繰り返しますが、これは私がそれを行う方法です。
関数toSpan
は再利用できます。
class App extends React.Component {
render() {
const data = [{id: `01`, name: `Hi`}, {id: `02`, name: `Hello`}]
const toSpan = ({id, name}) => <span key={id}>{name}</span>
return (
<div>{data.map(toSpan)}</div>
)
}
}
あなたは最もよく理解するためにこれを使うかもしれません
const data = [{id: 1, name: 'a'}, {id: 2, name: 'b'}];
export default class App extends React.Component {
render() {
return (
<div>
{data.map((data, dataIndex ) => <span key={dataIndex}>{data.name}</span>)}
</div>
);
}
}
ここで、名前が属性付きに属していることがわかります。