useMutation ?
- 데이터를 생성 / 업데이트 / 삭제할 때 주로 사용합니다. <-> useQuery
- optimistic update을 활용해서 성공을 예상하며 미리 UI부터 갱신할 수 있습니다.
Option
- onMutate: (variables:TVariables) => Promise<TContext|void>|TContext|void
- mutationFn이 실행되기 전에 먼저 실행할 함수입니다.
- mutation 함수가 전달받은 파라미터가 동일하게 전달됩니다.
- optimistic update 사용 시 유용한 함수입니다.
- 여기서 반환된 값은 onError, onSettled 함수에 전달됩니다.
- onSuccess: (data: TData, variables: TVariables, context?: TContext) => Promise<unknown> | void
- mutation()이 성공하면 결과를 전달할 때 실행 됩니다.
- invalidationQueries(QueryKey)로 해당 쿼리를 invalidate 하고 refetch
- setQueryData로 직접 캐싱된 쿼리 데이터를 수정. (Optimistic Update) refetch가 일어나지 않음.
- mutation()이 성공하면 결과를 전달할 때 실행 됩니다.
- onError: (err: TError, variables: TVariables, context?: TContext) => Promise<unknown> | void
- mutation이 에러를 만났을 때 실행됩니다.
- mutation이 에러를 만났을 때 실행됩니다.
- onSettled: (data: TData, error: TError, variables: TVariables, context?: TContext) => Promise<unknown> | void
- mutation()의 성공 / 에러 여부에 상관없이 해당 데이터를 전달받습니다.
- mutation()의 성공 / 에러 여부에 상관없이 해당 데이터를 전달받습니다.
- mutationFn (variables: TVariables) => Promise<TData>
- Required
- 비동기 작업을 수행하고 프로미스를 반환하는 함수입니다. (쉽게 말해 api 요청하는 함수)
- variables 는 mutate가 전달하는 객체입니다.
Return
- mutate: (variables: TVariables, { onSuccess, onSettled, onError }) => void
- mutation을 실행시키는 함수입니다.
- variables 는 mutationFn에 전달하는 객체입니다.
코드 예시
import React from "react";
import axios from "axios";
import { useMutation } from "react-query";
import "./App.css";
function App() {
const fetchAdd = async (info) => {
const { data } = await axios.post(`/add`, info);
return data;
};
const { mutate, isLoading, isSuccess, isError } = useMutation(fetchAdd, {
onMutate: (variables) => {
// variables : {id: 1}
console.log("onMutate", variables);
},
onError: (error, variables, context) => {
// error
},
onSuccess: (data, variables, context) => {
console.log("success", data, variables, context);
},
onSettled: (data, error, variables, context) => {
// end
},
});
const handleSubmit = () => {
// onMutate 실행 => 성공시 onSuccess 실행 => 끝나면 onSettled 실행
mutate({ id: 1 });
};
}
export default App;
update 이후 Get 요청을 통한 최신화
- react-query 장점으로 Update후에 Get 요청을 자동으로 진행 할 수 있습니다.
- mutation 함수가 성공할 때, unique key를 invalidateQueries에 넣어주면 됩니다.
- invalidateQueries가 실행되면 해당 Query는 무효화되며 refetching을 시도합니다.
- 즉 사용자가 새로고침을 하지 않아도 데이터가 갱신 됩니다.
const queryClient = useQueryClient();
const mutation = useMutation(fetch, {
onSuccess: () => {
// postTodo가 성공하면 todos로 맵핑된 useQuery api 함수를 실행합니다.
queryClient.invalidateQueries("key");
}
});
- 해당 Query에 대해 refetching을 원하지 않고 무효화만 원한다면 refetchActive 옵션을 사용합니다.
queryClient.invalidateQueries("key", {
refetchActive: false,
});
Optimistic Update
- useMutation이 성공할 것이라 가정하고 미리 화면의 UI를 바꾸고 나서, 결과에 따라 확정 / 롤백하는 방식입니다.
- setQueryData 옵션을 사용합니다.
import React from "react";
import axios from "axios";
import { useMutation } from "react-query";
import "./App.css";
function App() {
const fetchAdd = async (info) => {
const { data } = await axios.post(`/add`, info);
return data;
};
const queryClient = useQueryClient();
const { mutate, isLoading, isSuccess, isError } = useMutation(fetchAdd, {
onMutate: async (variables) => {
// 요청한 Query 취소 함수
// 즉 해당 Query에 대한 refetching을 막는 것 => onMutate에서 수행되는 것들을 덮어쓰지 않기 위해
await queryClient.cancelQueries("key");
// 기존 Query를 가져오는 함수 ( 존재하지 않으면 undefinde 반환 )
const previousValue = queryClient.getQueryData("key");
if (previousValue) {
// setQueryData(): Query의 캐시된 데이터를 즉시 업데이트하는 동기 함수 ( Query가 존재하지 않으면 생성 )
// 전달받은 variables값을 즉시 새로운 데이터로 업데이트
queryClient.setQueryData("key", (oldData) => [...oldData, variables]);
}
// 이전 값 리턴
return { previousValue };
},
onError: (error, variables, context) => {
if (context?.previousValue) {
// error가 발생하면 onMutate에서 반환된 값으로 다시 롤백
queryClient.setQueryData("key", context.previousValue);
}
},
onSuccess: (data, variables, context) => {},
onSettled: (data, error, variables, context) => {
// mutation이 완료되면 성공 유무와 관계없이 쿼리를 무효화 시키고 새로 갱신
queryClient.invalidateQueries("key");
},
});
const handleSubmit = () => {
// onMutate 실행 => 성공시 onSuccess 실행 => 끝나면 onSettled 실행
mutate({ id: 1 });
};
}
export default App;
참조
'Study > 실무' 카테고리의 다른 글
React-Router v6 (0) | 2022.10.05 |
---|---|
useQuery (0) | 2022.10.05 |
Typescript Type vs interface (0) | 2022.10.04 |
window.location.href vs useNavigate vs Link (0) | 2022.10.04 |
web3-react를 이용한 메타마스크,코인베이스 지갑 연동 (0) | 2022.10.04 |