メインコンテンツへスキップ
バージョン: v18.0.0

配列とリスト

これまで、構成されているコンポーネントの単一のインスタンスを持つコンポーネントしか扱っていませんでした。たとえば、ニュースフィードのストーリーを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を探します。topStorytopStoriesに置き換え、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キーを追加する

この時点で、画面に複数のストーリーが表示されるはずです!本格的なニュースフィードアプリになりつつあります。

Multiple stories

しかし、key属性を提供せずにコンポーネントの配列を表示しているというReactの警告も表示されます。

React missing key warning

この警告に注意を払うことは常に重要であり、特に、配列内のインデックスだけでなく、表示されるもののアイデンティティに基づいてキーを作成する必要があります。これにより、Reactは、順序が変わってもどのアイテムがどれであるかを知ることができるため、リストからのアイテムの並べ替えと削除を正しく処理できます。

幸いなことに、GraphQLノードには一般的にIDがあります。storyidフィールドを選択して、キーとして使用できます。

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リストはビルディングブロックとして引き続き使用します。

さあ、先に進みましょう!