지난 포스팅 보기
2022.09.14 - [프로그래밍/React] - React Query 알아보기 - 1
들어가며
안녕하세요. 오늘도 React Query 에 대해 알아보겠습니다.
지난편에는 개념과 간단한 세팅, 실습 + useQuery hook 을 알아봤는데요.
오늘은 값을 변경할 때 쓰이는 useMutation 쪽을 알아보고 실습도 해보려 합니다.
useMutation
useMutation 은 useQuery 와 달리 값을 변경, 추가, 삭제 하기 위해 사용하는 hook 입니다.
mutation 는 다음 표에 있는 상태 중 순간마다 단 한가지 상태로만 존재합니다.
isIdle or status === 'idle' | 현재 fresh/reset 상태 |
isLoading or status === 'loading' | 현재 실행중인 상태 |
isError or status === 'error' | 에러를 만난 상태 |
isSuccess or status === 'success' | mutation이 성공적이고 data 를 사용할 수 있는 상태 |
지난번처럼 fake api 를 사용해서 간단하게 실습을 해보겠습니다.
/libs/api.js
export const createPost = async (data) => {
const response = await client.post (`/posts`, {
data
});
return response.data;
}
title, body, userId 세가지를 request-body 로 하는 api 통신 로직을 구현해줍니다.
fake api 이기 때문에 통신이 되는 것 처럼 보이지만 실제로 값이 들어가거나 그러진 않습니다.
/components/Post.js
const [post, setPost] = useState({
title: '',
body: 'sample body',
useId: 1
});
request-body 로 쓰일 state 를 만들어줍니다. title 만 넣어볼거라 body 와 userId 는 그냥 기본값으로 두었습니다.
const postMutation = useMutation(createPost, {
onMutate: (variable) => {
console.log('onMutate', variable);
},
onError: (error, variable, context) => {
console.log('error', error, context)
},
onSuccess: (data, variables, context) => {
console.log('success', data, variables, context);
},
onSettled: () => {
console.log('end');
},
});
const handleSubmit = () => {
postMutation.mutate(post);
};
return (
<div>
<h1>Add new title</h1>
<input type="text" value={post.title} onChange={e => setPost({...post, title: e.target.value})} />
<p>{postMutation.isSuccess ? "success" : "pending"}</p>
<p>{postMutation.isError ? "error" : "pending"}</p>
<button onClick={handleSubmit}>추가</button>
<h1>Exist posts</h1>
<ul>
{data.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</div>
);
};
유저가 title 입력후 추가 버튼을 누를 시 handleSubmit 함수에 의해 post state 를 mutate 함수에 보냅니다.
mutation 의 수명 주기를 확인해보기 위해 직접 option 으로 onMutate, onError, onSuccess, onSettled 를 넣었습니다.
postMutation.isSuccess, postMutation.isError 모두 pending 대기 상태임을 볼 수 있습니다.
타이틀을 입력하고 추가 버튼을 누르면 차례대로 onMutate -> onSuccess -> onSettled (error 가 발생하지 않았단 가정 하에)
console 이 찍히는 걸 보실 수 있습니다.
또한 postMutation.isSuccess 도 success 상태가 되자 pending -> success 로 바뀌는 걸 볼 수 있습니다!
console 에 찍힌 success data 는
이렇게 101번째 Id 값이 정상적으로 온 걸 확인할 수 있습니다.
const postMutation = useMutation(createPost, {
retry: 3,
})
이렇게 retry 옵션을 주게 되면 mutation 오류 시 설정한 횟수만큼 재시도하게 됩니다.
Update 후 fetch
react query 는 데이터 update 후에 간단한 코드 한줄로 바로 fetch 함수를 재 실행 할 수 있습니다.
방법은 mutation 함수가 onSuccess 일 때, unique key 로 맵핑된 fetch 함수를 invalidateQueries 에 넣어주면 됩니다.
onSuccess: (data, variables, context) => {
console.log('success', data, variables, context);
queryClient.invalidateQueries('posts');
},
Parallel Queries
Parrallel Queries 즉, 병렬 쿼리는 fetch query 의 동시성을 높이기 위해 병렬로 처리하는 것 입니다.
JS 에서 Promise.all 을 통해 서로 연관 없는 fetch 를 병렬적으로 처리하던 것 처럼 useQuery 도 그냥 나란히 코드를 써주기만 하면 됩니다.
export const fetchComments = async () => {
const response = await client.get(`/comments`);
return response.data;
}
export const fetchTodos = async () => {
const response = await client.get(`/todos`);
return response.data;
}
간단한 실험을 위해 comments, todos 를 가져오는 fake api 를 추가했습니다.
const { isLoading, isError, data, error } = useQuery(['posts'], fetchPosts);
const commentQuery = useQuery(['comments'], fetchComments);
const todoQuery = useQuery(['todos'], fetchTodos);
이렇게 그냥 별도 작업 없이 작성해주면 Parallel 하게 실행됩니다.
동기적으로 fetch 시 start 시간을 보면 comments 수행 이후 todos fetch 를 시작하는 걸 알 수 있습니다.
반면 parallel query 시 거의 동시에 시작하는 걸 알 수 있습니다.
Promise.all 도 마찬가지!
// async - await
useEffect(() => {
const run = async () => {
await fetchComments();
await fetchTodos();
}
run();
}, []);
// parallel
const commentQuery = useQuery(['comments'], fetchComments);
const todoQuery = useQuery(['todos'], fetchTodos);
// Promise.all
useEffect(() => {
Promise.all([fetchComments(), fetchTodos()]);
}, []);
마치며
오늘은 react query 에서 데이터를 변경/삭제/추가 하는 작업을 도와주는 useMutation hook 을 알아 보았습니다.
번외로 병렬 쿼리에 대해서도 조금 실험해봤는데, 뭔가 react query 에서는 부가적으로 다른 작업 없이도 저렇게 병렬로 데이터를 잘 받아오는게 신기하기도 하고(?) .. 그렇네요.
'DEV > React' 카테고리의 다른 글
React Query 알아보기 - 1 (0) | 2022.09.14 |
---|---|
[책리뷰/서평] 초보자를 위한 리액트 200제, 정보문화사 (0) | 2021.04.03 |