型情報出力
Relayコンパイラは、通常の動作として、型安全なアプリケーションコードの作成に役立つ、選択した言語の型情報を生成します。これらの型は、relay-compiler
がオペレーションとフラグメントを記述するために生成する成果物に含まれています。
オペレーション変数
クエリ、ミューテーション、またはサブスクリプションオペレーションで使用される変数オブジェクトの形状。
この例では、生成された型情報は、変数オブジェクトにartistID
キー(非ヌルの文字列)が含まれている必要があることを示しています。
- Flow
- TypeScript
/**
* export type ExampleQuery$variables = {
* +artistID: string,
* }
* export type ExampleQuery$data = {
* +artist: {
* +name: ?string,
* }
* }
* export type ExampleQuery = {
* +variables: ExampleQuery$variables,
* +response: ExampleQuery$data,
* }
*/
const data = useLazyLoadQuery(
graphql`
query ExampleQuery($artistID: ID!) {
artist(id: $artistID) {
name
}
}
`,
// variables are expected to be of type ExampleQuery$variables
{artistID: 'banksy'},
);
/**
* export type ExampleQuery$variables = {
* readonly artistID: string
* }
* export type ExampleQuery$data = {
* readonly artist?: {
* readonly name?: string
* }
* }
* export type ExampleQuery = {
* readonly variables: ExampleQuery$variables
* readonly response: ExampleQuery$data
* }
*/
const data = useLazyLoadQuery(
graphql`
query ExampleQuery($artistID: ID!) {
artist(id: $artistID) {
name
}
}
`,
// variables are expected to be of type ExampleQuery$variables
{artistID: 'banksy'},
);
オペレーションとフラグメントデータ
データマスキングルールに従って、オペレーションまたはフラグメントで選択されたデータの形状(フラグメントスプレッドによって選択されたデータを除く)。
この例では、生成された型情報は、useLazyLoadQuery
(またはusePreloadedQuery
)によって返されるレスポンスデータの型を記述しています。
- Flow
- TypeScript
/**
* export type ExampleQuery$variables = {
* +artistID: string,
* }
* export type ExampleQuery$data = {
* +artist: {
* +name: ?string,
* }
* }
* export type ExampleQuery = {
* +variables: ExampleQuery$variables,
* +response: ExampleQuery$data,
* }
*/
// data is of type ExampleQuery$data
const data = useLazyLoadQuery(
graphql`
query ExampleQuery($artistID: ID!) {
artist(id: $artistID) {
name
}
}
`,
{artistID: 'banksy'},
);
return props.artist && <div>{props.artist.name} is great!</div>
/**
* export type ExampleQuery$variables = {
* readonly artistID: string
* }
* export type ExampleQuery$data = {
* readonly artist?: {
* readonly name?: string
* }
* }
* export type ExampleQuery = {
* readonly variables: ExampleQuery$variables
* readonly response: ExampleQuery$data
* }
*/
// data is of type ExampleQuery$data
const data = useLazyLoadQuery(
graphql`
query ExampleQuery($artistID: ID!) {
artist(id: $artistID) {
name
}
}
`,
{artistID: 'banksy'},
);
return props.artist && <div>{props.artist.name} is great!</div>
同様に、この例では、生成された型情報は、useFragment
が受け取ることを期待するフラグメント参照の型と一致するプロパティの型を記述しています。
- Flow
- TypeScript
/**
* export type ExampleFragmentComponent_artist$data = {
* +name: string
* }
*
* export type ExampleFragmentComponent_artist$key = { ... }
*/
import type { ExampleFragmentComponent_artist$key } from "__generated__/ExampleFragmentComponent_artist.graphql"
type Props = {
artist: ExampleFragmentComponent_artist$key,
};
export default ExampleFragmentComponent(props) {
// data is of type ExampleFragmentComponent_artist$data
const data = useFragment(
graphql`
fragment ExampleFragmentComponent_artist on Artist {
biography
}
`,
props.artist,
);
return <div>About the artist: {props.artist.biography}</div>;
}
/**
* export type ExampleFragmentComponent_artist$data = {
* readonly name: string
* }
*
* export type ExampleFragmentComponent_artist$key = { ... }
*/
import { ExampleFragmentComponent_artist$key } from "__generated__/ExampleFragmentComponent_artist.graphql"
interface Props {
artist: ExampleFragmentComponent_artist$key,
};
export default ExampleFragmentComponent(props: Props) {
// data is of type ExampleFragmentComponent_artist$data
const data = useFragment(
graphql`
fragment ExampleFragmentComponent_artist on Artist {
biography
}
`,
props.artist,
);
return <div>About the artist: {props.artist.biography}</div>;
}
フラグメント参照
データマスキングで説明されている不透明な識別子。子コンテナが親から受け取ることを期待しており、親のフラグメント内の子のフラグメントスプレッドを表します。
型安全なフラグメント参照チェックを有効にすることについては、重要な注意点をお読みください。
上記のフラグメントコンポーネントの例を合成するコンポーネントを考えてみましょう。この例では、子コンポーネントの生成された型情報は、フラグメント参照と呼ばれる一意の不透明な識別子型を受け取ります。これは、子のフラグメントがスプレッドされている場所の親のフラグメントの生成された型情報によって参照されます。これにより、子のフラグメントが親のフラグメントにスプレッドされ、実行時に正しいフラグメント参照が子コンポーネントに渡されることが保証されます。
- Flow
- TypeScript
import { ExampleFragmentComponent } from "./ExampleFragmentComponent"
/**
* import type { ExampleFragmentComponent_artist$fragmentType } from "ExampleFragmentComponent_artist.graphql";
*
* export type ExampleQuery$data = {
* +artist: ?{
* +name: ?string,
* +$fragmentSpreads: ExampleFragmentComponent_artist$fragmentType,
* }
* };
* export type ExampleQuery$variables = {
* +artistID: string,
* }
* export type ExampleQuery = {
* +variables: ExampleQuery$variables,
* +response: ExampleQuery$data,
* }
*/
// data is of type ExampleQuery$data
const data = useLazyLoadQuery(
graphql`
query ExampleQuery($artistID: ID!) {
artist(id: $artistID) {
name
...ExampleFragmentComponent_artist
}
}
`,
{artistID: 'banksy'},
);
// Here only `data.artist.name` is directly visible,
// the marker prop $fragmentSpreads indicates that `data.artist`
// can be used for the component expecting this fragment spread.
return <ExampleFragmentComponent artist={data.artist} />;
import { ExampleFragmentComponent } from "./ExampleFragmentComponent"
/**
* import { ExampleFragmentComponent_artist$fragmentType } from "ExampleFragmentComponent_artist.graphql";
*
* export type ExampleQuery$data = {
* readonly artist?: {
* readonly name: ?string,
* readonly " $fragmentSpreads": ExampleFragmentComponent_artist$fragmentType
* }
* }
* export type ExampleQuery$variables = {
* readonly artistID: string
* }
* export type ExampleQuery = {
* readonly variables: ExampleQuery$variables
* readonly response: ExampleQuery$data
* }
*/
// data is of type ExampleQuery$data
const data = useLazyLoadQuery(
graphql`
query ExampleQuery($artistID: ID!) {
artist(id: $artistID) {
name
...ExampleFragmentComponent_artist
}
}
`,
{artistID: 'banksy'},
);
// Here only `data.artist.name` is directly visible,
// the marker prop $fragmentSpreads indicates that `data.artist`
// can be used for the component expecting this fragment spread.
return <ExampleFragmentComponent artist={data.artist} />;
単一成果物ディレクトリ
重要な注意点として、デフォルトでは、厳密なフラグメント参照型情報は生成されません。代わりに、any
型として型付けされ、子コンポーネントに任意のデータを渡すことができます。
この機能を有効にするには、コンパイラにすべての成果物を単一ディレクトリに保存するように指示する必要があります。コンパイラ設定でartifactDirectory
を指定します。
{
// package.json
"relay": {
"artifactDirectory": "./src/__generated__",
...
},
...
}
さらに、.babelrc
の設定でBabelプラグインに成果物の場所を知らせる必要があります。
{
"plugins": [
["relay", { "artifactDirectory": "./src/__generated__" }]
]
}
ソースファイルで相対パスを指定する必要がないように、モジュール解決設定でこのディレクトリにエイリアスを付けることをお勧めします。これは、上記の例でも行われており、成果物は../../../../__generated__
のような相対パスではなく、__generated__
エイリアスからインポートされています。
背景情報
これは、relay-compiler
とその成果物出力はステートレスであるためです。つまり、元のソースファイルの場所と、コンパイラが以前にディスクに付随する成果物を保存した場所を追跡しません。したがって、コンパイラが他の成果物からフラグメント参照型をインポートしようとする成果物を生成する場合、コンパイラは
- まず、ディスク上の他の成果物がどこにあるかを知る必要があります。
- そして、他の成果物のディスク上の場所が変更されたときにインポートを更新する必要があります。
Facebookは、すべてのソースファイルがフラットな名前空間で考慮されるHasteと呼ばれるモジュールシステムを使用しています。これは、インポート宣言で別のモジュールへのパスを指定する必要がないことを意味し、したがってコンパイラが上記の問題を考慮する必要はありません。つまり、インポートはモジュールファイルのベース名のみを指定する必要があり、Hasteはインポート時に正しいモジュールを実際に検索します。ただし、Facebook以外では、Hasteモジュールシステムの使用は存在せず、推奨されていません。そのため、フラグメント参照型をインポートしない代わりにany
型として型付けするという決定がなされました。
最も単純な例として、Hasteをすべてのモジュールファイルを含む単一ディレクトリと考えることができます。そのため、すべてのモジュールインポートは、相対的な兄弟パスを使用して安全にインポートできます。これは、単一成果物ディレクトリ機能によって実現されます。ソースファイルと同じ場所に成果物を配置する代わりに、すべての成果物が単一ディレクトリに保存されるため、コンパイラはフラグメント参照型のインポートを生成できます。
このページは役に立ちましたか?
簡単な質問にお答えいただき、サイトをさらに改善するお手伝いをお願いします。 いくつかの簡単な質問にお答えください.