🖥️ const { error, isError } = useQuery({
queryKey: ['posts'],
queryFn: async (key) => {
throw new Error('An error occurred!');
},
})
console.log(error);
console.log(isError);
에러가 발생하면 isError 값이 true가 되고, 이에 따라 에러 메시지를 보여주도록 에러 처리를 구현한다.
🖥️ function HomePage() {
const {
data: postsData,
isPending,
isError,
} = useQuery({
queryKey: ['posts'],
queryFn: getPosts,
retry: 0,
});
if (isPending) return '로딩 중입니다...';
if (isError) return '에러가 발생했습니다.';
const posts = postsData?.results ?? [];
return (
<div>
<ul>
{posts.map((post) => (
<li key={post.id}>
{post.user.name}: {post.content}
</li>
))}
</ul>
</div>
);
}
탠스택 쿼리에서는 에러 발생 시 기본적으로 3번의 재시도를 한다.
코드를 테스트 할 때 retry 횟수를 0으로 조정하면 에러 화면을 더 빨리 볼 수 있어서 편리하다.
새로운 데이터를 추가할 때 사용하는 훅. 형태나 구조 변화를 뜻하는 뮤테이션은, 여기서는 사이드 이펙트를 가진 함수를 의미한다. 데이터베이스에 새 값을 추가하거나 수정하기, 삭제하기는 사이드 이펙트에 해당되고 이렇게 사이드 이펙트가 발생할 때 useMutaion() 훅을 사용하는 것이다.
useQuery()의 쿼리 함수는 컴포넌트가 마운트되면서 자동으로 실행되는 반면,
useMutation()은 실제로 뮤테이션 하는 함수를 직접 실행해 줘야 한다는 차이점이 있다.
mutate() 함수를 통해 mutationFn으로 등록했던 함수를 실행할 수 있고, 그래야 백엔드 데이터를 실제로 수정한다.
mutate()를 하면 백엔드 데이터는 변경되지만, 현재 캐시에 저장된 데이터는 refetch를 하지 않는 이상 기존 데이터가 그대로 남아있으므로, 변경된 데이터를 화면에 반영하려면 refetch가 필요하다.
🖥️ // 포스트 가져오는 함수
async function getPostsByUsername(username) {
const response = await fetch(`${BASE_URL}/posts?username=${username}`);
return await response.json();
}
🖥️ // 포스트 업로드 함수
async function uploadPost(newPost) {
const response = await fetch(`${BASE_URL}/posts`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(newPost),
});
if (!response.ok) {
throw new Error("포스트 업로드 실패");
}
return await response.json();
}
// 전체 코드
🖥️ import { useState } from 'react';
import { useMutation, useQuery } from '@tanstack/react-query';
import { getPosts, uploadPost } from './api';
function HomePage() {
const [content, setContent] = useState('');
const {
data: postsData,
isPending,
isError,
} = useQuery({
queryKey: ['posts'],
queryFn: getPosts,
retry: 0,
});
const uploadPostMutation = useMutation({
mutationFn: (newPost) => uploadPost(newPost),
});
const handleInputChange = (e) => {
setContent(e.target.value);
}
const handleSubmit = (e) => {
e.preventDefault();
const newPost = { username: 'codeit', content };
uploadPostMutation.mutate(newPost);
setContent('');
};
if (isPending) return '로딩 중입니다...';
if (isError) return '에러가 발생했습니다.';
const posts = postsData?.results ?? [];
return (
<>
<div>
<form onSubmit={handleSubmit}>
<textarea
name="content"
value={content}
onChange={handleInputChange}
/>
<button disabled={!content} type="submit">
업로드
</button>
</form>
</div>
<div>
<ul>
{posts.map((post) => (
<li key={post.id}>
{post.user.name}: {post.content}
</li>
))}
</ul>
</div>
</>
);
}
export default HomePage;
위 코드로는 업로드 버튼을 눌러도 새로 등록한 포스트가 화면에 보이지 않는다.
이는 mutate()를 한다고 캐시에 있는 데이터가 변경되는 것이 아니기 때문이다. 따라서 데이터를 refetch해야(예를 들어 화면 새로고침) 새로운 데이터도 보여줄 수 있다.
출처 : 코드잇 ReactQuery