GraphQL クエリ
GraphQL クエリは、graphQLSelector()
と graphQLSelectorFamily()
を使用して実行できます。(基盤となるサポートは、atom エフェクトによって提供されています)。ただし、まず最初にRelay 環境を設定する必要があります。
シンプルな GraphQL クエリ
graphQLSelector()
を使用して、GraphQL クエリと同期されたセレクターを作成できます。このセレクターは、GraphQL クエリと Recoil データフローグラフの同期を維持するのに役立ちます。GraphQL クエリに使用する変数
を決定したり、結果を変換したりするために、上流の Recoil アトム/セレクターに依存できます。Relay GraphQL ステートへのミューテーション、ローカル更新、遅延データ、またはライブクエリは、すべて自動的にセレクターと同期し、更新の原因となります。これにより、セレクターをローカルキャッシュとして扱い、サーバーを真実の情報源として扱うことができます。
const userNameQuery = graphQLSelector({
key: 'UserName',
environment: myEnvironmentKey,
query: graphql`
query UserNameQuery($id: ID!) {
user(id: $id) {
name
}
}
`,
variables: ({get}) => ({id: get(currentIDAtom)}),
mapResponse: data => data.user?.name,
});
function MyComponent() {
const seenCount = useRecoilValue(seenCountQuery);
return <span>{seenCount}</span>;
}
他の上流のアトム/セレクターを使用して GraphQL クエリ変数を計算することに加えて、graphQLSelector()
は、下流の他のセレクターによって派生状態を提供するためにも使用できます。
const pictureForUserState = selector({
key: 'PictureForUser',
get: async ({get}) => {
const username = get(userNameQuery);
const picture = await fetch(urlForUserNamePicture(username));
return picture;
},
});
パラメーター付きの GraphQL クエリ
graphQLSelectorFamily()
を使用すると、他の Recoil ステートに加えて、パラメーターを使用してクエリ変数を計算できます。パラメーターは、コンポーネントのプロパティ、React ステート、他の Recoil セレクターで使用されるなど、さまざまな方法で決定できます。
const userQuery = graphQLSelectorFamily({
key: 'UserQuery',
environment: myEnvironmentKey,
query: graphql`
query UserQuery($id: ID!, $clientID: ClientID!) {
user(id: $id, client_id: $clientID) {
name
address
}
}
`,
variables: id => ({get}) => ({id, clientID: get(clientIDAtom}),
mapResponse: data => data.user,
});
function MyComponent(props) {
const user = useRecoilValue(userQuery(props.userID));
return (
<div>
<h1>{user.name}</h1>
</div>
);
}
GraphQL フラグメント
GraphQL クエリには、GraphQL フラグメントを@inline
ディレクティブとreadInlineData()
を使用して含めることもできます。
const userNameFragment = graphql`
fragment UserNameFragment on User @inline {
name
}
`;
import {readInlineData} from 'relay-runtime';
const userNameQuery = graphQLSelectorFamily({
key: 'UserNameQuery',
environment: myEnvironmentKey,
query: graphql`
query UserNameQuery($id: ID!) {
user(id: $id) {
...UserNameFragment
}
}
`,
variables: id => ({id}),
mapResponse: response => {
const userFragment = readInlineData(userNameFragment, response.user);
return userFragment?.name;
},
})
GraphQL の事前フェッチ
GraphQL クエリは、事前フェッチパターンを使用して事前フェッチすることもできます。
function CurrentUserInfo() {
const currentUserID = useRecoilValue(currentUserIDState);
const userInfo = useRecoilValue(userInfoQuery(currentUserID));
const changeUser = useRecoilCallback(({snapshot, set}) => userID => {
// pre-fetch user info
snapshot.getLoadable(userInfoQuery(userID));
// change current user to start new render
set(currentUserIDState, userID);
});
return (
<div>
<h1>{userInfo.name}</h1>
<ul>
{userInfo.friends.map(friend =>
<li key={friend.id} onClick={() => changeUser(friend.id)}>
{friend.name}
</li>
)}
</ul>
</div>
);
}
プリロードされた GraphQL
EntryPointsを使用している場合、ページのJSの大部分をロードと並行してクエリをプリロードできます。
まず、アプリケーションのルートでプリロードされたクエリ用のEnvironmentKey
を登録する必要があります。
export const preloadedEnvironmentKey = new EnvironmentKey('preloaded');
export function AppRoot() {
const preloadedEnvironment = useRelayEnvironment();
return (
<RecoilRoot>
<RecoilRelayEnvironment
environmentKey={preloadedEnvironmentKey}
environment={preloadedEnvironment}>
{/* My App */}
</RecoilRelayEnvironment>
</RecoilRoot>
)
}
次に、クエリがこのpreloadedEnvironmentKey
を使用するように指示し、GraphQLに@preloadable
デコレーターを追加します。
export const userQuery = graphQLSelector({
key: 'UserQuery',
environmentKey: preloadedEnvironmentKey,
query: graphql`
query UserQuery($id: ID!) @preloadable {
user(id: $id) {
name
}
}
`,
variables: ({get}) => ({id: get(currentIDAtom)}),
mapResponse: data => data?.user,
});
最後に、このクエリを*.entrypoint.js
ファイルのプリロードされたクエリに追加します。
const MyEntryPoint = {
getPreloadProps: params => ({
queries: {
userQuery: {
parameters: require('UserQuery$Parameters'),
variables: {id: params.id},
},
}),
root: JSResource('m#MyApp.react'),
};