Day 44
strapi를 이용한 GraphQL 서버 만들기
- strapi GraphQL 설치
- GraphQL 서버에서 query와 mutation으로 post CRUD, login 해보기
Apollo Client 소개
Apollo Client란?
- React에서 GraphQL을 쉽게 사용할 수 있게 해주는 라이브러리이다.
- 상태 관리, fetching, 캐싱, mutation, automatic UI update도 지원해준다.
Apollo Client React 공식 문서
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| // const client = ...
client
.query({
query: gql`
query GetLocations {
locations {
id
name
description
photo
}
}
`,
})
.then((result) => console.log(result));
|
- gql은 template literal 문법을 이용해서 단순한 문자열을 graphql 문법으로 보여주는 함수이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| import React from 'react';
import * as ReactDOM from 'react-dom/client';
import { ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client';
import App from './App';
const client = new ApolloClient({
uri: 'https://flyby-router-demo.herokuapp.com/',
cache: new InMemoryCache(),
});
// Supported in React 18+
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<ApolloProvider client={client}>
<App />
</ApolloProvider>,
);
|
ApolloProvider
를 App에 감싸주어 apollo client를 사용할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
| // DisplayLocations.js
// Import everything needed to use the `useQuery` hook
import { useQuery, gql } from '@apollo/client';
const GET_LOCATIONS = gql`
query GetLocations {
locations {
id
name
description
photo
}
}
`;
function DisplayLocations() {
const { loading, error, data } = useQuery(GET_LOCATIONS);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error : {error.message}</p>;
return data.locations.map(({ id, name, description, photo }) => (
<div key={id}>
<h3>{name}</h3>
<img width="400" height="250" alt="location-reference" src={`${photo}`} />
<br />
<b>About this location:</b>
<p>{description}</p>
<br />
</div>
));
}
|
1
2
3
4
5
6
7
8
9
10
| // App.js
export default function App() {
return (
<div>
<h2>My first Apollo app 🚀</h2>
<br/>
<DisplayLocations />
</div>
);
}
|
gql
을 이용하여 graphql 쿼리를 만들고 useQuery
에 해당 변수를 대입함으로써 각 상태에 대한 값을 가져올 수 있다.
Queries
기본 사용법
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| import { gql, useQuery } from '@apollo/client';
const GET_DOGS = gql`
query GetDogs {
dogs {
id
breed
}
}
`;
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>
);
}
|
Caching query result
- graphql은 처음 서버에 query를 날리면 해당 query가 자동으로 클라이언트 단에 caching되기 때문에 굉장히 데이터를 빠르게 받아올 수 있다.
Polling
1
2
3
4
5
6
7
8
9
10
11
12
13
| 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= />
);
}
|
useQuery
에 option값으로 pollInterval
을 설정하면 0.5초마다 값을 갱신한다.
pollInterval
이 0이면 값을 갱신하지 않는다.
Refetching
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| 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= />
<button onClick={() => refetch({ breed: 'new_dog_breed' })}>
Refetch new breed!
</button>
</div>
);
}
<button
onClick={() =>
refetch({
breed: 'dalmatian', // Always refetches a dalmatian instead of original breed
})
}
>
Refetch!
</button>
|
- 위 코드처럼 refetch함수를 이용하여 어떤 특정 이벤트가 발생할 때마다 데이터를 fetch할 수 있다. 이때 인자를 다르게 해서 fetch할 수도 있다.
Loading status 확인
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| 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= />
<button onClick={() => refetch({ breed: 'new_dog_breed' })}>
Refetch!
</button>
</div>
);
}
|
- refetching할 때 로딩이 아니라 다른 걸 보여주고 싶을 때 networkStatus 변수를 이용할 수 있다.
useLazyQuery
- 컴포넌트가 자동으로 데이터를 받지 않고 사용자 이벤트를 이용하여 나중에 데이터를 fetch하고 싶다면
useLazyQuery()
를 사용할 수 있다.
Set a fetch policy
- 기본적으로 네트워크 호출을 통해서 데이터를 받아오고 내부적으로 캐싱하고 다음에 받아올 때는 캐시된 내용을 가져오는
cache-first
정책을 사용하고 있다.
- 이런 정책을 다른 정책을 사용하여 다르게 동작하도록 지정해줄 수 있다.
mutations
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| import { gql, useMutation } from '@apollo/client';
// Define mutation
const INCREMENT_COUNTER = gql`
# Increments a back-end counter and gets its resulting value
mutation IncrementCounter {
currentValue
}
`;
function MyComponent() {
// Pass mutation to useMutation
const [mutateFunction, { data, loading, error }] = useMutation(INCREMENT_COUNTER);
}
|
- 위와 같이 실행할 함수와 gql 변수를 넣어주면
useLazyQuery
와 비슷하게 쓸 수 있다.
GraphQL을 이용한 Todo 프로젝트 만들기