React Query 알아보기 - 2

2022. 9. 30. 01:36·DEV/React

react.. query 한테 조져지기 1초전

지난 포스팅 보기 

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 하게 실행됩니다.

async-await

동기적으로 fetch 시 start 시간을 보면 comments 수행 이후 todos fetch 를 시작하는 걸 알 수 있습니다.

parallel query

반면 parallel query 시 거의 동시에 시작하는 걸 알 수 있습니다.

Promise.all

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
'DEV/React' 카테고리의 다른 글
  • React Query 알아보기 - 1
  • [책리뷰/서평] 초보자를 위한 리액트 200제, 정보문화사
jobchae
jobchae
말하는 감자지만, 코드를 끄적이는 Node.js 백엔드 개발자입니다.
  • jobchae
    JOBCHAE
    jobchae
  • 전체
    오늘
    어제
    • 🚀 JOBCHAE (182)
      • DEV (151)
        • PS (108)
        • Node.js (12)
        • React (3)
        • docker (1)
        • 잡다한 개발 일지 (21)
        • injection (1)
        • JS, TS (3)
        • DB (2)
      • 축구 (0)
      • 일상 (19)
      • 영화 (3)
      • 음악 (8)
  • 블로그 메뉴

    • 💻 Github
    • 🙋🏻 Linkedin
    • 📖 방명록
  • 링크

    • PS Github
  • 공지사항

  • 인기 글

  • 태그

    nodejs
    슬랙
    앱잼
    DP
    백준
    JavaScript
    일상
    node.js
    Express
    이분탐색
    리액트
    BFS
    SOPT
    PS
    솝트
    위상정렬
    mongoDB
    개발
    db
    회고
    typescript
    렛츠락페스티벌
    알고리즘
    DFS
    react
    슬랙봇
    Nest.js
    boj
    우선순위큐
    GitHub
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
jobchae
React Query 알아보기 - 2
상단으로

티스토리툴바