本文へスキップ

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'),
};