useQuery
useQuery React hook 은 Apollo 애플리케이션에서 쿼리를 실행하기 위한 기본 API 입니다.
React 컴포넌트 내에서 쿼리를 실행하려면 useQuery GraphQL 쿼리 문자열을 호출하고 전달합니다.
컴포넌트가 랜더링되면 UI 를 랜더링하는데 사용할 수 있는
useQuery 는 아폴로 클라이언트로부터 객체를 리턴한다.
loading, error, data
예를 들어 보겠습니다.
GET_DOGS 라는 GraphQL 쿼리를 생성합니다.
import { gql, useQuery } from '@apollo/client';
const GET_DOGS = gql`
query GetDogs {
dogs {
id
breed
}
}
`;
다음으로 Dogs 라는 구성요소를 만들고, 그 안에서 GET_DOGS 쿼리를 useQuery 훅에 전달합니다.
function Dogs({ onDogSelected }) {
const { loading, error, data } = useQuery(GET_DOGS);
if (loading) return 'Loading...';
if (error) return `Error! ${error.message}`;
return (
<select name="dog" onChange={onDogSelected}>
{data.dogs.map(dog => (
<option key={dog.id} value={dog.breed}>
{dog.breed}
</option>
))}
</select>
);
}
쿼리가 실행되고, loading, error, data 값이 변경되면 Dogs 컴포넌트는 쿼리 상태에 따라 다양한 UI 요소를 지능적으로 랜더링할 수 있습니다.
loading 이 true : 쿼리가 아직 진행 중임을 나타내는 동안 컴포넌트는 Loading.. 을 표시합니다.
loading 이 false 이고 error 가 없다면 : query 는 완성된 것입니다.
컴포넌트는 서버에서 반환한 개 품종 목록으로 채워진 드롭다운 메뉴를 랜더링합니다.
사용자가 data 가 채워진 드롭다운에서 개 품종을 선택하면 그 선택 항목은 부모 컴포넌트로 전송됩니다 . (onDogSelected 통해서)
다음 단계에서는 드롭다운을 GraphQL 변수를 사용하는 보다 정교한 쿼리와 연결합니다.
Cashing query result
Apollo Client 는 서버에서 쿼리 결과를 가져올 때마다 자동으로 해당 결과를 로컬로 캐시합니다.
이렇게 하면 나중에 동일한 쿼리를 매우 빠르게 실행할 수 있습니다.
이 캐싱이 작동하는지 확인하기 위해 이라는 새 컴포넌트 DogPhoto 를 빌드해 보겠습니다 . DogPhoto 컴포넌트는 breed 라는 props 를 받아들입니다. 이 breed 는 드롭다운 메뉴의 현재 값을 반영함
const GET_DOG_PHOTO = gql`
query Dog($breed: String!) {
dog(breed: $breed) {
id
displayImage
}
}
`;
function DogPhoto({ breed }) {
const { loading, error, data } = useQuery(GET_DOG_PHOTO, {
variables: { breed },
});
if (loading) return null;
if (error) return `Error! ${error}`;
return (
<img src={data.dog.displayImage} style={{ height: 100, width: 100 }} />
);
}
이번에는 useQuery 훅에 구성옵션(variables)을 제공합니다.
variables 옵션은 우리가 GraphQL 쿼리에 전달하려는 모든 변수를 포함하는 객체입니다.
이 경우 우리는 드롭다운에서 현재 선택된 breed 를 전달하고자 합니다.
드롭다운에서 불독을 선택하여 해당 사진이 나타나는지 확인합니다. 그런 다음 다른 품종으로 전환한 다음 다시 bulldog 으로 돌아오면
불독 사진이 두번째로 로드되는 것을 알 수 있습니다. 이것은 작업 중인 캐시입니다.
다음으로 캐시된 데이터가 최신 상태인지 확인하는 몇가지 기술을 알아보겠습니다.
Updating cashed query results
쿼리의 캐시된 데이터가 서버의 데이터와 최신 상태인지 확인하려는 경우가 있습니다.
Apollo Client 는 이를 위해 두 가지 전략을 지원합니다. -> polling, refetching
Polling
Polling 은 지정된 간격으로 주기적으로 쿼리를 실행하여 서버와 거의 실시간으로 동기화합니다. 쿼리에 대한 폴링을 활성화하려면 밀리초 단위의 간격으로 pollInterval 구성 옵션을 useQuery 후크에 전달합니다.
function DogPhoto({ breed }) {
const { loading, error, data } = useQuery(GET_DOG_PHOTO, {
variables: { breed },
pollInterval: 500, });
if (loading) return null;
if (error) return `Error! ${error}`;
return (
<img src={data.dog.displayImage} style={{ height: 100, width: 100 }} />
);
}
pollInterval 을 500 으로 설정하면 0.5초마다 서버에서 현재 품종의 이미지를 가져옵니다.
pollInterval 을 0 으로 설정하면 쿼리가 polling 되지 않습니다.
단, useQeury 에서 반환되는 startPolling 및 stopPolling 함수를 사용하여 폴링을 동적으로 시작 및 중지할 수도 있습니다.
refetching
refetching 을 사용하면 고정 간격을 사용하는 대신 특정 사용자 작업에 대한 응답으로 쿼리 결과를 새로 고칠 수 있습니다.
이번엔 버튼을 DogPhoto 컴포넌트에 추가해보겠습니다. 이 컴포넌트는 버튼을 클릭할 때마다 쿼리의 refetch 함수를 호출합니다.
선택적으로 refetch 함수에 새 variables object 를 제공할 수 있습니다. 그렇지 않으면(다음 예의 경우와 같이) 쿼리는 이전 실행에서 사용한 것과 동일한 변수를 사용합니다.
function DogPhoto({ breed }) {
const { loading, error, data, refetch } = useQuery(GET_DOG_PHOTO, {
variables: { breed }
});
if (loading) return null;
if (error) return `Error! ${error}`;
return (
<div>
<img src={data.dog.displayImage} style={{ height: 100, width: 100 }} />
<button onClick={() => refetch()}>Refetch!</button>
</div>
);
}
버튼을 클릭하고 UI가 새로운 개 사진으로 업데이트되는 것을 확인하십시오. 다시 가져오는 것은 새로운 데이터를 보장하는 훌륭한 방법이지만 로드 상태에 약간의 복잡성이 발생합니다. 다음 섹션에서는 복잡한 로딩 및 오류 상태를 처리하기 위한 전략을 다룰 것입니다.
refetch 에 새로운 variables 제공
<button onClick={() => refetch({
breed: 'dalmatian' // Always refetches a dalmatian instead of original breed
})}>Refetch!</button>
원래 쿼리의 변수 중 일부 에 대해 새 값을 제공 하지만 모든 변수는 제공하지 않는 경우 refetch에서는 생략된 각 변수의 원래 값을 사용합니다.
Inspecting loading states (로딩 상태 검사)
useQuery 후크가 쿼리의 현재 loading 상태를 노출 하는 것을 이미 보았습니다 . 이것은 쿼리가 처음 로드될 때 유용하지만 refetching 이나 polling 할 때 loading 상태는 어떻게 됩니까?
이전 섹션의 refetch 예제로 돌아가 보겠습니다. 버튼을 클릭하면 새 데이터가 도착할 때까지 구성 요소가 다시 렌더링되지 않는 것을 볼 수 있습니다. 사진을 다시 가져오고 있음을 사용자에게 알리려면 어떻게 해야 합니까?
useQuery hook's result object 는 networkStatus 속성을 통해 쿼리 상태에 대한 세분화된 정보를 제공합니다 . 이 정보를 활용하기 위해 refetch 가 진행되는 동안 쿼리 컴포넌트가 다시 렌더링되도록 notifyOnNetworkStatusChange: true 옵션을 설정합니다.
import { NetworkStatus } from '@apollo/client';
function DogPhoto({ breed }) {
const { loading, error, data, refetch, networkStatus } = useQuery(
GET_DOG_PHOTO,
{
variables: { breed },
notifyOnNetworkStatusChange: true,
},
);
if (networkStatus === NetworkStatus.refetch) return 'Refetching!';
if (loading) return null;
if (error) return `Error! ${error}`;
return (
<div>
<img src={data.dog.displayImage} style={{ height: 100, width: 100 }} />
<button onClick={() => refetch()}>Refetch!</button>
</div>
);
}
notifyOnNetworkStatusChange: true 이 옵션을 활성화하면 networkStatus 속성에 의해서 = 세분화된 정보를 제공하는 것. 을 사용하지 않으려는 경우에도 그에 따라 loading 업데이트 값이 보장됩니다.
networkStatus 속성은 다양한 loading 상태를 나타내는 NetworkStatus enum 입니다.
Refetch는 NetworkStatus.refetch 로 표시되며 polling 및 pagination 에 대한 값도 있습니다. 가능한 모든 loading 상태의 전체 목록은 소스 를 확인하세요 .
(아 무슨 말인지 모르겠다...)
Inspecting error states
생략..
Manual execution with useLazyQuery
React가 useQuery 를 호출하는 컴포넌트를 렌더링할 때, Apollo Client 는 자동으로 해당 쿼리를 실행합니다. 그러나 사용자가 버튼을 클릭하는 것과 같은 다른 이벤트에 대한 응답으로 쿼리를 실행하려면 어떻게 해야 할까요?
useLazyQuery 후크는 컴포넌트 렌더링 외에 이벤트에 대한 응답으로 쿼리를 실행하는 데 적합합니다 . useQuery 와 달리 useLazyQuery 를 호출할 때 its associated query 를 즉시 실행하지 않습니다 . 대신 쿼리 를 실행할 준비가 될 때마다 호출 하는 쿼리 함수 를 결과 튜플에 반환합니다.
다음은 예입니다.
import React from 'react';
import { useLazyQuery } from '@apollo/client';
function DelayedQuery() {
const [getDog, { loading, error, data }] = useLazyQuery(GET_DOG_PHOTO);
if (loading) return <p>Loading ...</p>;
if (error) return `Error! ${error}`;
return (
<div>
{data?.dog && <img src={data.dog.displayImage} />}
<button onClick={() => getDog({ variables: { breed: 'bulldog' } })}>
Click me!
</button>
</div>
);
}
useLazyQuery의 반환 튜플 에서 첫 번째 항목은 쿼리 함수이고 두 번째 항목은 useQuery 에서 반환한 것과 동일한 결과 object 입니다.
위에 표시된 것처럼 쿼리 함수에 옵션을 전달하는 것처럼, 옵션을 useLazyQuery 에 전달할 수 있습니다. 둘 다에 특정 옵션을 전달하면 쿼리 함수에 전달한 값이 우선합니다. 이것은 default 옵션을 useLazyQuery 에 전달하는 편리한 방법이고, 그리고나서 쿼리 함수에서 해당 옵션을 커스터마이징하는 편리한 방법입니다.
지원되는 옵션의 전체 목록은 API 참조 를 참조 하십시오 .
Setting a fetch policy (가져오기 정책 세팅)
기본적으로 useQuery 후크는 Apollo 클라이언트 캐시를 확인하여 요청한 모든 데이터가 이미 로컬에서 사용 가능한지 확인합니다. 모든 데이터 를 로컬에서 사용할 수 있는 경우, useQuery 는 해당 데이터를 반환하고 GraphQL 서버를 쿼리 하지 않습니다 . 이 cache-first 정책은 Apollo 클라이언트의 default fetch policy 입니다.
주어진 쿼리에 대해 다른 fetch policy 을 지정할 수 있습니다. 그렇게 하려면 다음 useQuery 에 대한 호출에 fetchPolicy 옵션을 포함하십시오 .
const { loading, error, data } = useQuery(GET_DOGS, {
fetchPolicy: "network-only" // Doesn't check cache before making a network request
});
nextFetchPolicy
nextFetchPolicy 쿼리를 지정할 수도 있습니다. 그렇게 하면 쿼리의 첫 번째 실행에 fetchPolicy 가 사용되며 nextFetchPolicy 쿼리가 향후 캐시 업데이트에 응답하는 방식을 결정하는 데 사용됩니다.
const { loading, error, data } = useQuery(GET_DOGS, {
fetchPolicy: "network-only", // Used for first execution
nextFetchPolicy: "cache-first" // Used for subsequent executions
});
예를 들어, 쿼리가 항상 초기 네트워크 요청을 하도록 하고 싶지만 그 이후에는 캐시에서 읽기가 편한 경우에 유용합니다.
지원되는 fetch policy
cache-first | Apollo Client는 먼저 캐시에 대해 쿼리를 실행합니다. 요청된 모든 데이터가 캐시에 있으면 해당 데이터가 반환됩니다. 그렇지 않으면 Apollo Client가 GraphQL 서버에 대해 쿼리를 실행하고 캐싱 후 해당 데이터를 반환합니다. 애플리케이션에서 보낸 네트워크 요청 수를 최소화하는 데 우선 순위를 둡니다. 이것이 기본 가져오기 정책입니다. |
cache-only | Apollo Client 는 캐시에 대해서만 쿼리를 실행합니다. 이 경우 서버를 쿼리하지 않습니다. 캐시에 요청 된 cache-only모든 필드에 대한 데이터가 포함되어 있지 않으면 쿼리에서 오류가 발생합니다. |
cache-and-network | Apollo Client는 캐시 와 GraphQL 서버 모두에 대해 전체 쿼리를 실행 합니다. 서버 측 쿼리의 결과가 캐시된 필드를 수정하면 쿼리가 자동으로 업데이트됩니다. 캐시된 데이터를 서버 데이터와 일관성 있게 유지하는 데 도움이 되는 동시에 빠른 응답을 제공합니다. |
network-only | Apollo Client는 먼저 캐시를 확인 하지 않고 GraphQL 서버에 대해 전체 쿼리를 실행합니다 . 쿼리 결과 는 캐시에 저장됩니다. 서버 데이터와의 일관성을 우선시하지만 캐시된 데이터를 사용할 수 있을 때 거의 즉각적인 응답을 제공할 수 없습니다. |
no-cache | network-only쿼리 결과 가 캐시에 저장 되지 않는다는 점을 제외하면 과 유사 합니다. |
standby | 기본 필드 값이 변경될 때 cache-first이 쿼리가 자동으로 업데이트되지 않는다는 점을 제외하고 와 동일한 논리를 사용합니다 . 및 를 사용하여 이 쿼리를 수동으로 업데이트 할 수 있습니다 .refetchupdateQueries |
useQuery 후크는 다음 옵션을 허용합니다 .
작업 옵션 | |
query DocumentNode |
gql템플릿 리터럴 을 사용하여 AST로 구문 분석된 GraphQL 쿼리 문자열 입니다. useQuery쿼리가 후크에 대한 첫 번째 매개변수로 제공될 수 있으므로 후크에 대한 선택 사항 입니다. 구성 요소에 필요 합니다 Query. |
variables { [key: string]: any } |
쿼리를 실행하는 데 필요한 모든 GraphQL 변수를 포함하는 개체입니다. 개체의 각 키는 변수 이름에 해당하고 해당 키의 값은 변수 값에 해당합니다. |
errorPolicy ErrorPolicy |
쿼리가 GraphQL 오류와 부분 결과를 모두 반환하는 응답을 처리하는 방법을 지정합니다. 자세한 내용은 GraphQL 오류 정책 을 참조하세요 . 기본값은 none, 쿼리 결과에 오류 세부 정보가 포함되지만 일부 결과 는 포함 되지 않음 을 의미합니다. |
onCompleted (data: TData | {}) => void |
쿼리가 오류 없이 성공적으로 완료되었을 때(또는 errorPolicyis ignore이고 부분 데이터가 반환된 경우) 호출되는 콜백 함수입니다. 이 함수는 쿼리의 결과로 전달 data됩니다. |
onError (error: ApolloError) => void |
쿼리에 하나 이상의 오류가 발생할 때 호출되는 콜백 함수입니다( errorPolicyis 제외 ignore). 이 함수는 발생한 오류에 따라 개체 또는 배열 ApolloError을 포함하는 개체에 전달됩니다.networkErrorgraphQLErrors |
skip boolean |
인 경우 true쿼리가 실행 되지 않습니다 . 와 함께 사용할 수 없습니다 useLazyQuery. 이 속성은 Apollo Client의 React 통합의 일부이며 핵심 API 에서는 사용할 수 없습니다 .ApolloClient 기본값은 false입니다. |
displayName string |
React 개발자 도구에 표시할 구성 요소의 이름입니다. 기본값은 Query입니다. |
네트워킹 옵션 | |
pollInterval number |
쿼리가 업데이트된 결과를 폴링하는 간격(밀리초)을 지정합니다. 기본값은 0(폴링 없음)입니다. |
notifyOnNetworkStatusChange boolean |
인 경우 true진행 중인 쿼리의 관련 구성 요소는 네트워크 상태가 변경되거나 네트워크 오류가 발생할 때마다 다시 렌더링됩니다. 기본값은 false입니다. |
context Record<string, any> |
Apollo Link 를 사용하는 경우 이 객체는 context링크 체인을 따라 전달 되는 객체의 초기 값입니다 . |
ssr boolean |
서버 측 렌더링false 중에 쿼리 실행을 건너뛰려면 전달 합니다 . |
client ApolloClient |
ApolloClient쿼리를 실행하는 데 사용할 인스턴스입니다 . 기본적으로 컨텍스트를 통해 전달된 인스턴스가 사용되지만 여기에서 다른 인스턴스를 제공할 수 있습니다. |
캐싱 옵션 | |
fetchPolicy FetchPolicy |
쿼리가 실행되는 동안 Apollo Client 캐시와 상호 작용하는 방식을 지정합니다(예: 서버에 요청을 보내기 전에 캐시에서 결과를 확인하는지 여부). 자세한 내용 은 가져오기 정책 설정 을 참조하세요 . 기본값은 cache-first입니다. |
nextFetchPolicy FetchPolicy |
이 실행 후fetchPolicy 이 쿼리의 모든 실행에 사용할 것을 지정합니다 . 예를 들어, 이를 사용 하여 단일 실행을 사용한 후 또는 cache-first가져오기 정책 으로 다시 전환할 수 있습니다 .cache-and-networknetwork-only |
returnPartialData boolean |
인 경우 캐시에 쿼리된 모든 필드 에 대한 결과가 포함되어 있지 않으면 쿼리가 캐시에서 부분true 결과를 반환할 수 있습니다. 기본값은 false입니다. |
더 이상 사용되지 않는 옵션 | |
partialRefetch boolean |
더 이상 사용되지 않습니다. 인 경우 쿼리 결과가 부분적으로 감지되면 쿼리가 발생합니다 true. refetch보다 일관된 가져오기 정책 적용 덕분에 Apollo Client 3에서는 이 옵션을 설정할 필요가 없습니다. 향후 릴리스에서 제거될 수 있습니다. 기본값은 false입니다. |
결과
호출된 후 useQuery 후크는 다음 속성을 가진 결과 개체를 반환합니다. 이 개체에는 쿼리 결과와 함께 다시 가져오기, 동적 폴링 및 페이지 매김을 위한 몇 가지 유용한 기능이 포함되어 있습니다.
운영 데이터 | |
data TData |
완료 후 GraphQL 쿼리의 결과를 포함하는 개체입니다. 이 값은 undefined쿼리로 인해 하나 이상의 오류가 발생하는 경우일 수 있습니다( 쿼리에 따라 다름 errorPolicy). |
previousData TData |
이 쿼리 의 가장 최근 이전 실행 결과를 포함하는 개체 입니다. 이 값은 undefined쿼리의 첫 번째 실행인 경우입니다. |
error ApolloError |
쿼리가 하나 이상의 오류를 생성하는 경우 이 개체에는 의 배열 graphQLErrors또는 단일 networkError. 그렇지 않으면 이 값은 undefined입니다. 자세한 내용은 작업 오류 처리 를 참조하십시오 . |
variables { [key: string]: any } |
쿼리에 제공된 변수를 포함하는 개체입니다. |
네트워크 정보 | |
loading boolean |
인 경우 true쿼리가 아직 진행 중이고 결과가 아직 반환되지 않았습니다. |
networkStatus NetworkStatus |
쿼리와 연결된 요청의 현재 네트워크 상태를 나타내는 숫자입니다. 가능한 값을 참조하십시오. notifyOnNetworkStatusChange옵션 과 함께 사용됩니다 . |
client ApolloClient |
쿼리를 실행한 Apollo Client의 인스턴스입니다. 후속 쿼리를 수동으로 실행하거나 캐시에 데이터를 쓰는 데 유용할 수 있습니다. |
called boolean |
이면 true연결된 지연 쿼리가 실행된 것입니다. 이 필드는 에서 반환한 결과 개체에만 있습니다 useLazyQuery. |
도우미 기능 | |
refetch (variables?: Partial<TVariables>) => Promise<ApolloQueryResult> |
선택적으로 new 를 전달하여 쿼리를 다시 실행할 수 있는 함수입니다 variables. 다시 가져오기가 네트워크 요청을 수행하도록 하기 위해 fetchPolicy로 설정됩니다 network-only(원래 쿼리 fetchPolicy가 네트워크 요청을 보장하는 no-cache또는 cache-and-network인 경우 제외). 다시 가져오기 도 참조하십시오 . |
fetchMore ({ query?: DocumentNode, variables?: TVariables, updateQuery: Function}) => Promise<ApolloQueryResult> |
페이지가 매겨진 목록 필드 에 대한 다음 결과 집합을 가져오는 데 도움이 되는 함수입니다 . |
startPolling (interval: number) => void |
쿼리가 지정된 간격(밀리초)에서 다시 실행을 시작하도록 지시하는 함수입니다. |
stopPolling () => void |
에 대한 이전 호출 후 폴링을 중지하도록 쿼리에 지시하는 함수입니다 startPolling. |
subscribeToMore (options: { document: DocumentNode, variables?: TVariables, updateQuery?: Function, onError?: Function}) => () => void |
일반적으로 쿼리에 포함된 특정 필드를 구독하기 위해 구독 을 실행할 수 있는 기능입니다 . 이 함수는 구독을 종료하기 위해 호출할 수 있는 다른 함수를 반환합니다. |
updateQuery (previousResult: TData, options: { variables: TVariables }) => TData |
후속 GraphQL 작업을 실행하지 않고 쿼리의 캐시된 결과를 업데이트할 수 있는 기능입니다. |
https://www.apollographql.com/docs/react/data/queries/
'🌸 GraphQL' 카테고리의 다른 글
Prisma Client 필터링 (0) | 2022.04.04 |
---|---|
GraphQL server 공식문서 참고 (0) | 2022.03.26 |
데이터 유지를 prisma 를 통해 하자 (CRUD) (0) | 2022.02.28 |
nexus 이해하기3 (공식문서 참고) (0) | 2022.02.26 |
nexus 이해하기2 (공식문서 참고) (0) | 2022.02.26 |