はじめに
現在触っているシステムで、Relay
を使用しているため、まず理解するために、チュートリアルを行いました。
そこで学んだ内容を、ここにアウトプットいたします。
バージョン18.0.0
のDocsを参照しています。
GraphQLの解説は、行いません。
Relayとは
一言でいうと、GraphQLを使ったデータ取得・キャッシュ・同期を最適化し、UIの一貫性を保つためのライブラリです。
そのため、GraphQLとRelayはセットで使用します。
メリット
Relay
の最大のメリットは、各コンポーネントが独自のデータ要件をローカルで宣言し、それらの要件をより大きなクエリにまとめることができます。
(※ ↑ 公式ドキュメント参照)
各コンポーネントで、Fragmentを用意して、それを大元のクエリで結合させます。
そうすることで、修正が発生した際に、各コンポーネントごとで修正ができます。
デメリット
チュートリアルをやってみましたが、学習コストは高いなと思いました。
直感的に分かる。というより、Relay
独自の概念があるので、そこはしっかり抑える必要があるなと思います。
仕組み
(※ ↑ 公式ドキュメント参照)
Relay runtime
がコアエンジンとなり、サーバーに向けて、クエリを実行してくれます。
この図から分かるように、各コンポーネントでFragment
を大元のクエリに結合させます。
実装例
import { graphql } from 'relay-runtime';
import { useLazyLoadQuery } from "react-relay";
import type {NewsfeedQuery as NewsfeedQueryType} from './__generated__/NewsfeedQuery.graphql';
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>
);
}
const NewsfeedQuery = graphql`
query NewsfeedQuery {
topStories {
id
...StoryFragment
}
}
`;
(※ ↑ 公式ドキュメント参照)
NewsfeedQuery
で、graphql
でマークされた文字列リテラルを用意します。
これを用意すると、Relay
がコンパイルしてくれます。
query NewsfeedQuery {
となっているので、これが大元のクエリとなっています。
これを、useLazyLoadQuery
でクエリを実行してくれます。
また、...StoryFragment
がFragment
になって、各コンポーネントで定義をしていきます。
import { graphql } from 'relay-runtime';
import { useFragment } from 'react-relay';
import type {StoryFragment$key} from './__generated__/StoryFragment.graphql';
import StoryCommentsSection from './StoryCommentsSection';
type Props = {
story: StoryFragment$key;
};
export default function Story({story}: Props) {
const data = useFragment(
StoryFragment,
story,
);
return (
<Card>
<Heading>{data.title}</Heading>
<PosterByline poster={data.poster} />
<Timestamp time={data.createdAt} />
<Image image={data.thumbnail} width={400} height={400} />
<StorySummary summary={data.summary} />
<StoryCommentsSection story={data} />
</Card>
);
}
const StoryFragment = graphql`
fragment StoryFragment on Story {
title
summary
createdAt
poster {
...PosterBylineFragment
}
thumbnail {
...ImageFragment @arguments(width: 400)
}
...StoryCommentsSectionFragment
}
`;
(※ ↑ 公式ドキュメント参照)
上記が、子コンポーネントになります。
fragment StoryFragment on Story
で、Fragment
で定義しています。
それを、useFragment
で実行いたします。
もしFragmentに修正が入れば、コンポーネントごとに修正できるので、わざわざ大元のクエリを変更して...みたいな手間はありません。
図にすると、以下のイメージです。
(※ ↑ 公式ドキュメント参照)
コンパイルの方法
Relayは変更すると、必ずコンパイルをし直す必要があります。
これを忘れてしまうと、エラーが出続けてしまいます。
"scripts": {
"relay": "relay-compiler",
...
package.json
に上記のように記載すると、npm run relay
でコンパイルを実行してくれます。
newsfeed % npm run relay
> newsfeed@0.0.0 relay
> relay-compiler
[INFO] [default] compiling...
[INFO] [default] compiled documents: 17 reader, 5 normalization, 18 operation text
[INFO] Done.
まとめ
上記までで、Relay
を使用して、データ取得するまでの基本は抑えられたかと思います。
まだこの他にも、学ぶべき箇所はあるかと思います。
- ページネーション
- データの再取得 ...etc
メジャーバージョンによっても、実装方法は異なると思うので、扱っているシステムでどのような実装をしているか、確認しようと思います。
ドキュメントは、全て英語になっています。
チュートリアル等は、翻訳をうまく使いながら、挑戦してみてください。
最後までご覧いただき、ありがとうございました。