API에 몇가지 옵션을 추가하여 style을 꾸미는 작업을 하였다. reactJS에서 style을 적용하기 위해서는 css을 file로 import하여 component.style props에 적용했었는데 이번에는 styled-compnents module
을 설치하여 진행하였다.
https://github.com/RoJaebl/movieql-client/commit/31ac2373836108ae9f7b5b110f0ce708d2b47373
간단한 예시로 아래와 같이 styled를 사용한 코드를 구현하였다. div tag에 style을 정의한 형태를 component로 사용하는걸 볼 수 있다.
import styled from "styled-components";
const Container = styled.div`
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
`;
export default function Movies() {
return (
<Container>
</Container>
);
}
Local only field는 백엔드에 있는 API에 가지 않고도 추가적인 데이터를 얻어오는 방법이다. 아래 코드를 보면 graphQL에서 type Movie는 isLiked를 구현하지 않았다.
const GET_MOVIE = gql`
query getMovie($movieId: String!) {
movie(id: $movieId) {
id
title
description_full
medium_cover_image
rating
isLiked @client
}
}
useQuery의 동작을 보면 apollo cache에 전달된 정보를 가지고 API에 요청을 보내게 되고 resolvers를 호출하여 필요한 데이터를 전달받게 된다. 하지만 전달된 요소가 API에 없는 요소라면 에러가 발생하게되고 데이터를 얻어오는데 실패한다.
여기서 API를 요청하면서 백엔드에 없는 데이터를 받기 위해서는 위 코드와 같이 추가로 요청하는 요소 옆에 @client keyword
를 덧붙혀 local only field라는걸 명시한다.
export default function Movie() {
const { id } = useParams();
const { data, loading } = useQuery(GET_MOVIE, {
variables: {
movieId: id,
},
});
console.log(id, data, loading);
return (
<Container>
<Column>
<Title>{loading ? "Loading..." : `${data?.movie?.title}`}</Title>
<Description>{data?.movie?.description_full}</Description>
<Subtitle>⭐️ {data?.movie?.rating}</Subtitle>
<button>{data?.movie?.isLiked ? "Unlike" : "Like"}</button>
</Column>
<Image bg={data?.movie?.medium_cover_image} />
</Container>
);
}
아직 isLiked기능을 구현하지 않았지만 button tag를 보면 현재 JS파일에서 추가한 데이터를 useQuery로 반환된 데이터처럼 사용할 수 있게 된다. 이것이 graphQL의 강력한 기능이라고 할 수 있다.
Local only field는 apollo cache 데이터를 API로 요청하지 않는 요소이다. 즉, local only field는 cache 안에서 등록이 되는데 개발자가 apollo cache에 접근하기 위해서는 useApolloClien
와 useQuery중 하나로 접근
하여 apollo cach에서 API 데이터와 같이 전달 받을 수 있다.
export default function Movie() {
const { id } = useParams();
const { client: { cache } } = useQuery(GET_MOVIE, {
variables: {
movieId: id,
},
});
const onClick = () => {
cache.writeFragment({
id: `Movie:${id}`,
fragment: gql`
fragment MovieFragment on Movie {
isLiked
}
`,
data: {
isLiked: !data.movie.isLiked,
},
});
};
return (
<button onClick={onClick}>
{data?.movie?.isLiked ? "Unlike" : "Like"}
</button>
);
}