지난 실습에 이어서 이번에는 각 post의 comment를 받아오는 useQuery훅을 작성해보자
interface IPostDetailProps {
post: IPost;
}
interface IComments {
id: number;
email: string;
body: string;
}
async function fetchComments(postId: number) {
const response = await fetch(
`https://jsonplaceholder.typicode.com/comments?postId=${postId}`
);
return response.json();
}
export function PostDetail({ post }: IPostDetailProps) {
// replace with useQuery
const {data, isLoading, isError} = useQuery<IComments[]>('comments', () => fetchComments(post.id));
// fetchComments는 postId를 인자로 받기 때문에 익명함수로 감싸서 작성한다
return (
<>
<h3 style={{ color: "blue" }}>{post.title}</h3>
<button>Delete</button> <button>Update title</button>
<p>{post.body}</p>
<h4>Comments</h4>
{
isError && <div>ERROR!</div>
}
{
isLoading ?(
<div>Loading...</div>
) : (
data?.map((comment) => (
<li key={comment.id}>
{comment.email}: {comment.body}
</li>
))
)
}
</>
);
}
comments를 잘 받아오지만 문제가 있다.
다른 게시글을 클릭해도 처음 받아온 comment를 보여준다.
이유는 모든 쿼리가 comments 쿼리 키를 동일하게 사용하고 있기 때문
이다.
이렇게 comments 같이 알려진 쿼리 키가 있을 때는 어떠한 트리거
가 있어야만 데이터를 다시 가져오게 된다
새 게시물 제목을 클릭할 때는 이런 트리거가 일어나지 않기 때문에 data refetch가 일어나지 않는 것이다.
각 게시물 쿼리에 대한 라벨을 설정한다
각 쿼리에 대한 라벨을 설정하면 comments 쿼리에 대한 캐시를 공유하지 않고 각 쿼리에 해당하는 캐시를 가지게 될 것이다.
쿼리 키에 문자열 대신 배열을 전달한다
['comments', post.id]
쿼리 키를 쿼리에 대한 의존성 배열
로 취급하게 된다.
이렇게 하면 모든 comments 쿼리가 같은 쿼리로 간주되는 상황을 막고 각기 다른 쿼리로 다뤄질 것이다.
interface IPostDetailProps {
post: IPost;
}
interface IComments {
id: number;
email: string;
body: string;
}
async function fetchComments(postId: number) {
const response = await fetch(
`https://jsonplaceholder.typicode.com/comments?postId=${postId}`
);
return response.json();
}
export function PostDetail({ post }: IPostDetailProps) {
// replace with useQuery
const {data, isLoading, isError} = useQuery<IComments[]>(['comments', post.id], () => fetchComments(post.id));
// fetchComments는 postId를 인자로 받기 때문에 익명함수로 감싸서 작성한다
// 쿼리 키를 의존성 배열로 작성하여 post.id마다 각기 다른 쿼리를 생성
return (
<>
<h3 style={{ color: "blue" }}>{post.title}</h3>
<button>Delete</button> <button>Update title</button>
<p>{post.body}</p>
<h4>Comments</h4>
{
isError && <div>ERROR!</div>
}
{
isLoading ?(
<div>Loading...</div>
) : (
data?.map((comment) => (
<li key={comment.id}>
{comment.email}: {comment.body}
</li>
))
)
}
</>
);
}
각 게시물마다 다른 comment 쿼리를 가진다