apollo-client를 우선 설치해줘야 한다.
$ npm install @apollo/client graphql
React에서 graphQL server와 연결 할 때 우선 apollo client 생성이 필요하다.
따로 apolloClient.js 파일을 만들어 준다.
import { ApolloClient, InMemoryCache, split, HttpLink } from '@apollo/client';
import { getMainDefinition } from '@apollo/client/utilities';
import { GraphQLWsLink } from '@apollo/client/link/subscriptions';
import { createClient } from 'graphql-ws';
const httpLink = new HttpLink({
uri: 'http://localhost:4000',
});
const wsLink = new GraphQLWsLink(createClient({ url: `ws://localhost:4000` }));
const splitLink = split(
({ query }) => {
const definition = getMainDefinition(query);
return (
definition.kind === 'OperationDefinition' &&
definition.operation === 'subscription'
);
},
wsLink,
httpLink
);
const client = new ApolloClient({
link: splitLink,
cache: new InMemoryCache(),
});
export default client;
코드에서는 httpLink와 wsLink를 각각 만들어줬다.
Apollo Client는 WebSocketLink를 사용하여 모든 작업 유형을 실행할 수 있지만 대부분의 경우 query 및 mutation에 HTTP를 계속 사용해야 한다.
그 이유는 query 및 mutation는 상태 저장 또는 장기간 연결이 필요하지 않으므로 WebSocket 연결이 아직 존재하지 않는 경우 HTTP의 효율성과 확장성이 향상되기 때문,
이를 지원하기 위해 @apollo/client 라이브러리는 boolean 검사 결과에 따라 두 개의 서로 다른 링크 중 하나를 사용할 수 있는 split 함수를 제공한다.
WebSocketLink와 HttpLink를 모두 초기화 하고
split 함수를 사용하여 실행 중인 연산의 유형에 따라
하나를 사용하거나 다른 하나를 사용하는 단일 Link로
두 링크를 결합 할 수 있다.
ApolloProvider는 Apollo Client를 컨텍스트에 배치하여 구성 요소 트리의 모든 위치에서 액세스할 수 있도록 해준다.
여기서 ApolloProvider는 client props를 받는데
값은 아까 생성한 apolloClient다.
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import { ApolloProvider } from '@apollo/client';
import client from './apolloClient';
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
root.render(
<React.StrictMode>
<ApolloProvider client={client}>
<App />
</ApolloProvider>
</React.StrictMode>
);
ApolloProvider가 연결되면 query를 시작할 수 있다.
Apollo Client는 useQuery hooks와 gql을 제공한다.
gql은 실제 서버로 보낼 쿼리문을 작성 하게 해준다.
템플릿 리터럴을 이용해 쿼리문을 작성한다.
실제로 필요한 쿼리문을 작성한다.
const getChatting = gql`
query {
chatting {
id
writer
description
}
}
`;
컴포넌트에서 실제로 쿼리를 useQuery를 이용해 날려보자
useQuery에 금방 생성한 getChatting을 인자로 넣어준다.
const { loading, error, data } = useQuery(getChatting);
useQuery는 구성 요소가 렌더링될 때마다 자동으로 쿼리를 실행한다.
그리고 결과로 loading, error, data 개체를 반환한다.
사실, 이 외에도 subscribeToMore등 여러 값을 반환하지만,
현재 는 이 셋만 다뤄본다.
loading: loading은 말 그대로 load중 임을 boolean값으로 나타낸다.
error: 쿼리에 실패 했을 때 error가 반환되며, error 객체처럼 사용 가능하다.
data: 쿼리의 결과가 반환되면 data에 값이 첨부된다.
const Home: FC = () => {
const { loading, error, data } = useQuery(getChatting);
return (
<div>
<div>
{loading
? 'Loading...'
: data.chatting.map((chat: any) => (
<h3 key={chat.id}>
{chat.writer}: {chat.description}
</h3>
))}
</div>
</div>
);
};
export default Home;
해당 컴포넌트를 렌더시킬 부분에 렌더 시켜주면 쿼리가 자동으로 실행된다.