useMutation
import { useMutation } from "react-query";
const { data, isLoading, mutate } = useMutation(mutationFn, options);
useMutation hook은 인자로 2가지를 받는다. useQuery 처럼 key 값은 따로 없다.
- mutationFn: mutate를 위한 패치함수 (필수)
- options: 옵션 (선택)
mutationFn 함수로 POST, PUT, DELETE 및 각 요청에 필요한 인자들이 포함된다.
또한, options로 설정하는 값들, 그리고 반환되는 프로퍼티들은 아래와 같은 값들이 있다. (공식문서 참고)
options
- onMutate
mutation 전에 실행되는 함수로, 미리 렌더링 하고자 할 때 유용하다.
이 함수가 반환하는 값을 아래 함수들의 context로 사용가능.
(variables) => Promise<Context> | void
- onSuccess
mutation 이 성공하고 결과를 전달할 때 실행
(data, variables, context?) => void
- onError
mutation 이 실패했을 시 에러를 전달한다.
(error, variables, context?) => void
- onSettled
mutation 의 성공/실패 여부와 상관없이 완료됐을 때 실행
(data, error, variables, context?) => void
이 외에도 mutationKey, retry, cacheTime 등 다양한 옵션이 존재한다.
returns
- mutate
mutation 을 실행시키는 메서드로 가장 많이 쓰인다.
variables 매개변수가 mutationFn 으로 전달되며, 옵션의 메서드들은 위 Options 함수들과 동일하다.
* 단 두 곳 모두에서 콜백을 실행하면, Options 콜백 -> mutate 옵션의 콜백 순으로 실행된다.
(variables, { onSuccess, onError, onSettled }) => void
- mutateAsync
mutate 결과를 Promise로 반환한다.
mutation 결과를 다루거나 비동기 연쇄로직이 필요한 경우 유용하나, catch() 로 에러 핸들링을 직접 해야한다는 유의점이 있다.
(variables, { onSuccess, onError, onSettled }) => Promise<Data>
이외 에도 status(idle, loading, error, success), data, isLoading, error, isError 등 다양한 값을 반환한다.
POST 요청
1. Hook 제작
// src/hooks/apis/useSuperHeroQuery.js
import { useMutation, useQuery, useQueryClient } from "react-query";
import axios from "axios";
const fetchAddSuperHero = (hero) => {
return axios.post("http://localhost:4000/superheroes", hero)
}
export const useAddSuperHeroMutation = () => {
return useMutation(fetchAddSuperHero)
}
- mutationFn인 fetchAddSuperHero() 함수를 만든다. axios.post를 반환하며, body에 값으로 담을 hero를 인자로 받는다. (이 hero 값은, 추후 useMutation() 의 mutate 메서드를 통해 전달)
- useAddSuperHeroMutation() 훅을 제작한다. 이는, useMutation() 자체를 반환하며, 인자로 패치 함수와 옵션 등을 설정한다.
2. 적용
import { useState } from "react";
import { Link } from "react-router-dom";
import { useSuperHeroesQuery, useAddSuperHeroMutation } from "../hooks/apis/useSuperHeroesQuery";
export const RQSuperHeroesPage = () => {
const [newHero, setNewHero] = useState({ name: "", alterEgo: "" });
const { isLoading, data, isError, error, refetch } = useSuperHeroesQuery();
// 1) useAddSuperHeroMutation() Hooks 가져오기
const { mutate: addHero, isLoading2, isError2, error2 } = useAddSuperHeroMutation(newHero)
// 2) mutate() 함수 실행부
const handleClickAddButton = () => {
addHero(newHero)
setNewHero({ name: "", alterEgo: "" })
}
if (isLoading) return <h2>Loading...!!</h2>;
if (isError) return <h2>{error.message}</h2>;
return (
<>
<h2>React Query Super Heroes Page</h2>
<div>
<input
value={newHero.name}
onChange={(e) =>
setNewHero((prev) => ({ ...prev, name: e.target.value }))
}
placeholder="name"
/>
<input
value={newHero.alterEgo}
onChange={(e) =>
setNewHero((prev) => ({ ...prev, alterEgo: e.target.value }))
}
placeholder="alterEgo"
/>
<button onClick={handleClickAddButton}>Add Hero</button>
</div>
<button onClick={refetch}>refresh</button>
{data?.data.map((hero) => (
<div key={hero.name}>
<Link to={`/rq-super-hero/${hero.id}`}>{hero.name}</Link>
</div>
))}
</>
);
};
- useAddSuperHeroMutation 훅을 가져온다. useMutation() 이 반환하는 프로퍼티들을 사용할 수 있으며, 여기서 특히 mutate() 함수를 사용하는 것이 중요하다.
- mutate() 함수를 addHero 라는 네이밍으로 가져왔다. 이는, mutation을 실행하는 함수이며, newHero를 인자로 전달하면 이는 useAddSuperHeroMutation() 훅에서 useMutation()의 첫번째 인자인 mutationFn에 전달된다.
- button을 클릭했을 때, hadleClickAddButton 핸들러 함수가 실행된다. 이 때, 포함된 mutate() 함수 역시 실행될 것이다.
출처