配列とリスト
これまで、構成されているコンポーネントの単一のインスタンスを持つコンポーネントしか扱っていませんでした。たとえば、ニュースフィードのストーリーを1つだけ表示しており、そのストーリー内には、単一の作者と単一のプロフィール写真しかありません。複数のものをどのように扱うかを見てみましょう。
GraphQLは配列をサポートしており、GraphQLではリストと呼ばれています。フィールドは、単一のスカラー値だけでなく、それらの配列、または単一のエッジだけでなく、エッジの配列になることができます。スキーマは各フィールドがリストであるかどうかを指定しますが、奇妙なことに、GraphQLクエリ構文は、単一のフィールドを選択することとリストを選択することの区別をしません。これは、GraphQLレスポンスはクエリと同じ形状であるべきという設計原則に対する奇妙な例外です。
リクエスト
query MyQuery {
viewer {
contacts { // List of edges
id // field on a single item
name
}
}
}
レスポンス
{
viewer: {
contacts: [ // array in response
{
id: "123",
name: "Chris",
},
{
id: "789",
name: "Sue",
}
]
}
}
実は、私たちの例アプリのスキーマには、現在使用している単一のストーリーを返すtopStory
フィールドとは異なり、ストーリーのリストを返すtopStories
フィールドがあります。
ニュースフィードに複数のストーリーを表示するには、Newsfeed.tsx
を修正してtopStories
を使用するだけです。
ステップ1 - フラグメント内でリストを選択する
Newsfeed.tsx
を開き、NewsfeedQuery
を探します。topStory
をtopStories
に置き換え、npm run relay
を実行します。
const NewsfeedQuery = graphql`
query NewsfeedQuery {
topStories {
...StoryFragment
}
}
`;
ステップ2 - コンポーネント内でリストをマップする
Newsfeed
コンポーネントでは、data.topStories
は、それぞれがそのストーリーを表示するためにStory
子コンポーネントに渡すことができるフラグメント参照の配列になります。
export default function Newsfeed({}) {
const data = useLazyLoadQuery<NewsfeedQueryType>(NewsfeedQuery, {});
const stories = data.topStories;
return (
<div className="newsfeed">
{stories.map(story => <Story story={story} />)}
</div>
);
}
ステップ3 - ノードIDに基づいてReactキーを追加する
この時点で、画面に複数のストーリーが表示されるはずです!本格的なニュースフィードアプリになりつつあります。
しかし、key属性を提供せずにコンポーネントの配列を表示しているというReactの警告も表示されます。
この警告に注意を払うことは常に重要であり、特に、配列内のインデックスだけでなく、表示されるもののアイデンティティに基づいてキーを作成する必要があります。これにより、Reactは、順序が変わってもどのアイテムがどれであるかを知ることができるため、リストからのアイテムの並べ替えと削除を正しく処理できます。
幸いなことに、GraphQLノードには一般的にIDがあります。story
のid
フィールドを選択して、キーとして使用できます。
const NewsfeedQuery = graphql`
query NewsfeedQuery {
topStories {
id
...StoryFragment
}
}
`;
...
export default function Newsfeed({}) {
const data = useLazyLoadQuery<NewsfeedQueryType>(NewsfeedQuery, {});
const stories = data.topStories;
return (
<div className="newsfeed">
{stories.map(story => (
<Story
key={story.id}
story={story}
/>
)}
</div>
);
}
これで、画面上にStoryのコレクションが表示されます。ここで、クエリ内の同じ場所に個々のフィールドとフラグメントスプレッドを混在させていることに注意してください。これは、Newsfeedが(useLazyLoadQuery
から直接)必要なフィールドを読み取り、Storyが(useFragment
を介して)必要なフィールドを読み取ることができることを意味します。同じオブジェクトは、Newsfeedが選択したフィールドid
を含み、StoryFragment
のフラグメントキーでもあります。
GraphQLリストは、もののコレクションを扱うための最も基本的な方法にすぎません。チュートリアルの後半では、コネクションと呼ばれる特別なシステムを使用して、ページネーションと無限スクロールを行うために、それらをさらに構築します。アイテムのコレクションがあるほとんどの場合にコネクションを使用する必要がありますが、GraphQLリストはビルディングブロックとして引き続き使用します。
さあ、先に進みましょう!